@shijiu/jsview-vue 0.9.502 → 0.9.590

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.
Files changed (215) hide show
  1. package/dom/bin/jsview-browser-debug-dom.min.js +1 -1
  2. package/dom/bin/jsview-dom.min.js +1 -1
  3. package/dom/target_core_revision.js +4 -3
  4. package/index.js +10 -0
  5. package/package.json +8 -1
  6. package/patches/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js +16 -5
  7. package/samples/AnimPicture/App.vue +89 -106
  8. package/samples/Basic/App.vue +65 -68
  9. package/samples/Basic/components/ContentBlock.vue +31 -36
  10. package/samples/Basic/components/anim/AnimGroup.vue +61 -75
  11. package/samples/Basic/components/anim/AnimKeyframeBasic.vue +54 -43
  12. package/samples/Basic/components/anim/AnimKeyframeComposite.vue +25 -31
  13. package/samples/Basic/components/anim/AnimTransition.vue +142 -105
  14. package/samples/Basic/components/div/DivBackground.vue +38 -16
  15. package/samples/Basic/components/div/DivClip.vue +143 -78
  16. package/samples/Basic/components/div/DivCssScoped.vue +10 -10
  17. package/samples/Basic/components/div/DivCssVar.vue +40 -42
  18. package/samples/Basic/components/div/DivGroup1.vue +45 -39
  19. package/samples/Basic/components/div/DivGroup2.vue +56 -45
  20. package/samples/Basic/components/div/DivLayout.vue +34 -5
  21. package/samples/Basic/components/div/DivRadius.vue +51 -42
  22. package/samples/Basic/components/div/DivTransform.vue +21 -16
  23. package/samples/Basic/components/panel/Panel1.vue +46 -44
  24. package/samples/Basic/components/panel/Panel2.vue +22 -26
  25. package/samples/Basic/components/panel/TitleBar.vue +12 -12
  26. package/samples/Basic/components/text/TextAlign.vue +54 -44
  27. package/samples/Basic/components/text/TextEmoji.vue +16 -20
  28. package/samples/Basic/components/text/TextFontStyle.vue +77 -53
  29. package/samples/Basic/components/text/TextGroup1.vue +46 -38
  30. package/samples/Basic/components/text/TextGroup2.vue +25 -28
  31. package/samples/Basic/components/text/TextOverflow.vue +76 -57
  32. package/samples/BasicFocusControl/App.vue +22 -43
  33. package/samples/BasicFocusControl/components/BaseBlock.vue +42 -43
  34. package/samples/BasicFocusControl/components/MainArea.vue +55 -70
  35. package/samples/BasicFocusControl/components/MainAreaLeftBlock.vue +11 -15
  36. package/samples/BasicFocusControl/components/MainAreaRightBlock.vue +21 -24
  37. package/samples/BasicFocusControl/components/SideBar.vue +32 -47
  38. package/samples/BasicFocusControl/components/SideBarBlock.vue +20 -23
  39. package/samples/ColorSpace/App.vue +15 -24
  40. package/samples/DemoHomepage/App.vue +7 -11
  41. package/samples/DemoHomepage/components/BodyFrame.vue +19 -9
  42. package/samples/DemoHomepage/components/TabFrame.vue +7 -8
  43. package/samples/DemoHomepage/router.js +32 -33
  44. package/samples/DemoHomepage/views/Homepage.vue +24 -8
  45. package/samples/FilterDemo/AnimatePic.vue +58 -0
  46. package/samples/FilterDemo/App.vue +99 -61
  47. package/samples/FilterDemo/VideoLayer.vue +62 -0
  48. package/samples/FlipCard/App.vue +32 -41
  49. package/samples/FlipCard/FlipCard.vue +48 -54
  50. package/samples/GridDemo/App.vue +109 -77
  51. package/samples/GridDemo/ButtonBlock.vue +50 -49
  52. package/samples/GridDemo/FocusItem.vue +19 -38
  53. package/samples/GridDemo/Item.vue +46 -54
  54. package/samples/HashHistory/App.vue +63 -79
  55. package/samples/HashHistory/components/HorizontalButtonList.vue +72 -95
  56. package/samples/HashHistory/components/Item.vue +42 -56
  57. package/samples/HashHistory/router.js +23 -12
  58. package/samples/HashHistory/views/MainPage.vue +35 -46
  59. package/samples/HashHistory/views/SubPage.vue +34 -47
  60. package/samples/Input/App.vue +2 -3
  61. package/samples/Input/FullKeyboard.vue +2 -6
  62. package/samples/Input/InputPanel.vue +2 -3
  63. package/samples/Input/KeyboardItem.vue +1 -1
  64. package/samples/LongImage/App.vue +11 -27
  65. package/samples/LongImage/Button.vue +50 -145
  66. package/samples/LongImage/ButtonItem.vue +44 -0
  67. package/samples/LongImage/LongImageScroll.vue +71 -106
  68. package/samples/LongImage/Scroll.vue +7 -9
  69. package/samples/LongText/App.vue +13 -28
  70. package/samples/LongText/Button.vue +43 -145
  71. package/samples/LongText/ButtonItem.vue +44 -0
  72. package/samples/LongText/LongTextScroll.vue +68 -101
  73. package/samples/LongText/Scroll.vue +7 -9
  74. package/samples/Marquee/App.vue +34 -37
  75. package/samples/MaskClip/App.vue +17 -30
  76. package/samples/MetroWidgetDemos/Advanced/App.vue +211 -0
  77. package/samples/MetroWidgetDemos/Advanced/ButtonItem.vue +90 -0
  78. package/samples/MetroWidgetDemos/Item.vue +67 -0
  79. package/samples/{SimpleWidgetDemo → MetroWidgetDemos/PerformanceTest}/App.vue +80 -104
  80. package/samples/{SimpleWidgetDemo → MetroWidgetDemos/PerformanceTest}/Item.vue +7 -0
  81. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/bg.jpg +0 -0
  82. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/coupon_content.png +0 -0
  83. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/coupon_left.png +0 -0
  84. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/coupon_mid.png +0 -0
  85. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/coupon_right.png +0 -0
  86. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/focus_border.png +0 -0
  87. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/holder_logo.png +0 -0
  88. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/jrbm.png +0 -0
  89. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/line_left.png +0 -0
  90. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/line_mid.png +0 -0
  91. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/line_right.png +0 -0
  92. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/loading.png +0 -0
  93. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/logo.png +0 -0
  94. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/mcjx.png +0 -0
  95. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/tao.png +0 -0
  96. package/samples/{ClassNameDemo → MetroWidgetDemos/PerformanceTest}/assets/tmall.png +0 -0
  97. package/samples/{SimpleWidgetDemo → MetroWidgetDemos/PerformanceTest}/border.png +0 -0
  98. package/samples/{SimpleWidgetDemo → MetroWidgetDemos/PerformanceTest}/components/ContentItem.vue +60 -86
  99. package/samples/{SimpleWidgetDemo → MetroWidgetDemos/PerformanceTest}/components/MyTab.vue +0 -0
  100. package/samples/MetroWidgetDemos/PerformanceTest/data.js +45 -0
  101. package/samples/MetroWidgetDemos/PingPong/App.vue +135 -0
  102. package/samples/MetroWidgetDemos/PingPong/AppPage.vue +58 -0
  103. package/samples/MetroWidgetDemos/PingPong/AppTab.vue +69 -0
  104. package/samples/MetroWidgetDemos/PingPong/Item.vue +92 -0
  105. package/samples/MetroWidgetDemos/PingPong/ViewSwiper.vue +214 -0
  106. package/samples/MetroWidgetDemos/Simple/App.vue +194 -0
  107. package/samples/MetroWidgetDemos/WidgetItem.vue +89 -0
  108. package/samples/MetroWidgetDemos/data.js +204 -0
  109. package/samples/NinePatchDemo/App.vue +114 -115
  110. package/samples/NinePatchDemo/Item.vue +7 -8
  111. package/samples/Preload/App.vue +61 -63
  112. package/samples/Preload/Item.vue +21 -29
  113. package/samples/QrcodeDemo/App.vue +24 -29
  114. package/samples/SoundPool/App.vue +77 -106
  115. package/samples/SprayView/App.vue +10 -8
  116. package/samples/SpriteImage/App.vue +1 -2
  117. package/samples/TextBox/App.vue +86 -101
  118. package/samples/TextBox/RenderCenter.vue +1 -1
  119. package/samples/TextBox/RenderLeft.vue +1 -1
  120. package/samples/TextBox/RenderOneLine.vue +1 -1
  121. package/samples/TextBox/RenderRight.vue +1 -1
  122. package/samples/TextShadowDemo/App.vue +1 -2
  123. package/samples/TextureAnimation/App.vue +16 -13
  124. package/samples/TextureSize/App.vue +15 -25
  125. package/samples/ThrowMoveDemo/AccelerateDemo.vue +2 -4
  126. package/samples/ThrowMoveDemo/LRParabolicDemo.vue +2 -3
  127. package/samples/ThrowMoveDemo/TargetDemo.vue +3 -4
  128. package/samples/ThrowMoveDemo/UDParabolicDemo.vue +2 -3
  129. package/samples/TouchSample/App.vue +2 -3
  130. package/samples/TouchSample/Item.vue +15 -13
  131. package/samples/TouchSample/MetroWidgetHorizontal.vue +2 -2
  132. package/samples/TouchSample/MetroWidgetVertical.vue +1 -1
  133. package/samples/TouchSample/TouchContainerHorizontal.vue +4 -3
  134. package/samples/TouchSample/TouchContainerVertical.vue +3 -2
  135. package/samples/TransitPage/App.vue +20 -32
  136. package/samples/VideoDemo/App.vue +65 -81
  137. package/samples/VideoDemo/components/Button.vue +41 -52
  138. package/samples/VideoDemo/components/Controllor.vue +171 -169
  139. package/samples/VideoDemo/components/VideoFrame.vue +87 -99
  140. package/samples/VisibleSensorDemo/App.vue +167 -0
  141. package/scripts/jsview-jsmap-serve.js +42 -0
  142. package/scripts/jsview-post-install.js +1 -1
  143. package/tsconfig.json +3 -0
  144. package/utils/JsViewEngineWidget/JsvFocusBlock.vue +204 -193
  145. package/utils/JsViewEngineWidget/JsvFocusManager.js +30 -17
  146. package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +1555 -1656
  147. package/utils/JsViewEngineWidget/MetroWidget/PageUpdater.js +136 -0
  148. package/utils/JsViewEngineWidget/MetroWidget/ToolFunctions.js +18 -0
  149. package/utils/JsViewEngineWidget/TemplateParser.js +111 -1
  150. package/utils/JsViewEngineWidget/WidgetCommon.js +8 -2
  151. package/utils/JsViewEngineWidget/index.js +4 -4
  152. package/utils/JsViewPlugin/JsvPlayer/GetVersion.js +1 -1
  153. package/utils/JsViewPlugin/JsvPlayer/JsvMedia.js +264 -54
  154. package/utils/JsViewPlugin/JsvPlayer/JsvPlayer.vue +5 -1
  155. package/utils/JsViewPlugin/JsvPlayer/version.js +5 -5
  156. package/utils/JsViewVueTools/JsvRefTaker.js +35 -0
  157. package/utils/JsViewVueTools/index.js +19 -0
  158. package/utils/JsViewVueWidget/BrowserDebugWidget/BrowserQrcode.vue +8 -4
  159. package/utils/JsViewVueWidget/JsvFilterView.vue +59 -51
  160. package/utils/JsViewVueWidget/JsvGrid.vue +139 -41
  161. package/utils/JsViewVueWidget/JsvMaskClipDiv.vue +3 -1
  162. package/utils/JsViewVueWidget/JsvNativeSharedDiv.vue +8 -17
  163. package/utils/JsViewVueWidget/JsvNinePatch.vue +1 -1
  164. package/utils/JsViewVueWidget/JsvPosterDiv.vue +37 -7
  165. package/utils/JsViewVueWidget/JsvPosterImage.vue +34 -13
  166. package/utils/JsViewVueWidget/JsvPreload/JsvPreload.vue +2 -12
  167. package/utils/JsViewVueWidget/JsvQrcode/JsvQrcode.vue +1 -1
  168. package/utils/JsViewVueWidget/JsvSpray/JsvSpray.vue +13 -10
  169. package/utils/JsViewVueWidget/JsvSpriteAnim/index.js +2 -3
  170. package/utils/JsViewVueWidget/JsvTextureAnim/JsvTextureAnim.vue +25 -21
  171. package/utils/JsViewVueWidget/JsvTransparentDiv.vue +7 -8
  172. package/utils/JsViewVueWidget/JsvVisibleSensor/JsvVisibleSensor.vue +141 -0
  173. package/utils/JsViewVueWidget/JsvVisibleSensor/index.js +9 -0
  174. package/utils/JsViewVueWidget/index.js +42 -0
  175. package/samples/AdvanceMetroWidget/App.vue +0 -123
  176. package/samples/AdvanceMetroWidget/Frame.vue +0 -102
  177. package/samples/AdvanceMetroWidget/Item.vue +0 -63
  178. package/samples/AdvanceMetroWidget/data.js +0 -137
  179. package/samples/ClassNameDemo/App.vue +0 -119
  180. package/samples/ClassNameDemo/components/ContentItem.vue +0 -253
  181. package/samples/ClassNameDemo/components/LoadingView.vue +0 -43
  182. package/samples/ClassNameDemo/components/TitleView.vue +0 -24
  183. package/samples/ClassNameDemo/data.js +0 -24
  184. package/samples/FlowMultiWidget/App.vue +0 -91
  185. package/samples/FlowMultiWidget/assets/nine_patch_focus.png +0 -0
  186. package/samples/FlowMultiWidget/components/Block.vue +0 -107
  187. package/samples/FlowMultiWidget/components/FlowPage.vue +0 -60
  188. package/samples/FlowMultiWidget/components/Item.vue +0 -103
  189. package/samples/FlowMultiWidget/components/MenuItem.vue +0 -72
  190. package/samples/FlowMultiWidget/components/MyMenu.vue +0 -90
  191. package/samples/FlowMultiWidget/data.js +0 -446
  192. package/samples/HashHistory/views/BasePage.vue +0 -19
  193. package/samples/HashHistory/views/SubPageFirst.vue +0 -10
  194. package/samples/HashHistory/views/SubPageSecond.vue +0 -10
  195. package/samples/SimpleWidgetDemo/assets/bg.jpg +0 -0
  196. package/samples/SimpleWidgetDemo/assets/coupon_content.png +0 -0
  197. package/samples/SimpleWidgetDemo/assets/coupon_left.png +0 -0
  198. package/samples/SimpleWidgetDemo/assets/coupon_mid.png +0 -0
  199. package/samples/SimpleWidgetDemo/assets/coupon_right.png +0 -0
  200. package/samples/SimpleWidgetDemo/assets/focus_border.png +0 -0
  201. package/samples/SimpleWidgetDemo/assets/holder_logo.png +0 -0
  202. package/samples/SimpleWidgetDemo/assets/jrbm.png +0 -0
  203. package/samples/SimpleWidgetDemo/assets/line_left.png +0 -0
  204. package/samples/SimpleWidgetDemo/assets/line_mid.png +0 -0
  205. package/samples/SimpleWidgetDemo/assets/line_right.png +0 -0
  206. package/samples/SimpleWidgetDemo/assets/loading.png +0 -0
  207. package/samples/SimpleWidgetDemo/assets/logo.png +0 -0
  208. package/samples/SimpleWidgetDemo/assets/mcjx.png +0 -0
  209. package/samples/SimpleWidgetDemo/assets/tao.png +0 -0
  210. package/samples/SimpleWidgetDemo/assets/tmall.png +0 -0
  211. package/samples/SimpleWidgetDemo/data.js +0 -124
  212. package/utils/JsViewEngineWidget/MetroWidget/ContentView.vue +0 -63
  213. package/utils/JsViewEngineWidget/MetroWidget/DivWrapper.vue +0 -51
  214. package/utils/JsViewEngineWidget/MetroWidget/ItemView.vue +0 -213
  215. package/utils/JsViewEngineWidget/MetroWidget/RootView.vue +0 -154
@@ -2,7 +2,7 @@
2
2
  * @Author: ChenChanghua
3
3
  * @Date: 2021-09-22 16:08:58
4
4
  * @LastEditors: ChenChanghua
5
- * @LastEditTime: 2022-05-17 13:01:47
5
+ * @LastEditTime: 2022-07-13 10:29:51
6
6
  * @Description: file content
7
7
  -->
8
8
 
@@ -70,6 +70,10 @@
70
70
  "direction": {EdgeDirection}边缘方向,
71
71
  "rect": 到达边缘时的区域{x: 0, y: 0, width: 0,height: 0}
72
72
  }
73
+ onScroll {function} 滚动时的回调 (visibleStart, visibleRange, totalSize) => {}
74
+ visibleStart: 可视区域的起点
75
+ visibleRange: 可视区域大小(不含padding)
76
+ totalSize: 所有item的总长
73
77
  *
74
78
  * enableTouch {boolean} 支持触控
75
79
  * loadAll {boolean} 加载不显示的view,触控场景使用
@@ -126,8 +130,8 @@
126
130
  slideTo: {Function} (targetPosition : int, doAnim : Boolean) => void
127
131
  滚动到指定位置,注意这个位置是 item 的布局坐标,另外当某些item需要接管滚动时,itemConfig中takeOverSlide要为true。
128
132
  }
129
- * onEdge: 若单元格内另有可接管按键的控件(如SimpleWidget),该控件到达边缘需要通知SimpleWidget时的回调
130
- * onAction: 单元格内控件需要通过onAction.register方法向SimpleWidget注册 item 的回调,回调函数有
133
+ * onItemEdge: 若单元格内另有可接管按键的控件(如MetroWidget),该控件到达边缘需要通知MetroWidget时的回调
134
+ * onAction: 单元格内控件需要通过onAction.register方法向MetroWidget注册 item 的回调,回调函数有
131
135
  onFocus, onBlur, onClick, onWidgetEdge
132
136
  *
133
137
  * Q: 如何进行布局,定制每个格的尺寸?
@@ -150,16 +154,25 @@
150
154
  *
151
155
  * Q: item内是可获焦的元素时该如何处理?
152
156
  * A: 焦点处理: item内的元素需要在注册的onFocus和onBlue回调中管理焦点. 即在onFocus时把焦点设置到内部的可获焦节点;
153
- onBlur时将焦点给回父SimpleWidget, 注意此时是焦点树上的子节点往父节点切换, 此时为了把子节点blur掉,
157
+ onBlur时将焦点给回父MetroWidget, 注意此时是焦点树上的子节点往父节点切换, 此时为了把子节点blur掉,
154
158
  requestFocus函数需要传递一个false参数
155
159
  -->
156
- <script>
157
- /* eslint-disable no-unused-vars */
158
160
 
159
- import { ref, reactive } from "vue";
160
- import RootView from "./RootView.vue";
161
+ <script setup>
162
+ /* eslint-disable */
163
+ import {
164
+ ref,
165
+ reactive,
166
+ shallowRef,
167
+ onMounted,
168
+ onBeforeUnmount,
169
+ onUpdated,
170
+ toRaw,
171
+ nextTick,
172
+ } from "vue";
161
173
  import Forge from "../ForgeDefine";
162
- import { TemplateParser } from "../TemplateParser";
174
+ import { TemplateParser, TemplateItemAdder } from "../TemplateParser";
175
+ import { PageUpdater } from "./PageUpdater";
163
176
  import { SingleRangeModel } from "../RangeModel";
164
177
  import Dispatcher from "./Dispatcher";
165
178
  import {
@@ -170,254 +183,18 @@ import {
170
183
  SlideSetting,
171
184
  SeamlessSlide,
172
185
  } from "../WidgetCommon";
173
-
174
- let emptyFunc = () => {};
175
- // randomColor() {
176
- // let randomColor = Math.round(Math.random() * 2 ** 24).toString(16);
177
- // return (
178
- // "#" + new Array(6 - randomColor.length).fill("0").join("") + randomColor
179
- // );
180
- // },
181
-
182
- class TemplateItemAdder {
183
- constructor(template_parser, data, measure_func, page_range, side_effect) {
184
- this._TemplateParser = template_parser;
185
- this._Data = data;
186
- this._PageRange = page_range;
187
- this._MeasureFunc = measure_func;
188
- this._CurIndex = 0;
189
- this._CurPage = 0;
190
- this._KeyIndex = 0; //分页处的item
191
- this._SideEffect = side_effect;
192
- this._Key =
193
- this._TemplateParser._Template.Orient.type === HORIZONTAL
194
- ? "xPos"
195
- : "yPos";
196
- }
197
-
198
- tryAddItem(cur_item = null, page_num = 1) {
199
- let added = false;
200
- if (
201
- this._CurIndex < this._Data.length &&
202
- (!cur_item ||
203
- cur_item[this._Key] >= (this._CurPage - 1) * this._PageRange)
204
- ) {
205
- while (this._CurIndex < this._Data.length) {
206
- let item = this._TemplateParser.ParseTemplateItem(
207
- this._MeasureFunc(this._Data[this._CurIndex]),
208
- this._Data[this._CurIndex]
209
- );
210
- this._SideEffect?.(item);
211
- this._CurIndex++;
212
- if (item[this._Key] >= (this._CurPage + page_num) * this._PageRange) {
213
- this._CurPage += page_num;
214
- break;
215
- }
216
- }
217
- this._TemplateParser.CalculateNeighborWhenAddStop();
218
- added = true;
219
- }
220
- // 添加完成需要计算neighbor
221
- return added;
222
- }
223
-
224
- tryAddItemByPosition(position) {
225
- const page_num = Math.ceil(position / this._PageRange + 1);
226
- if (page_num > this._CurPage) {
227
- this.tryAddItem(null, page_num - this._CurPage);
228
- }
229
- }
230
-
231
- tryAddItemByIndex(index) {
232
- let added = false;
233
- while (this._CurIndex <= index) {
234
- added = true;
235
- let item = this._TemplateParser.ParseTemplateItem(
236
- this._MeasureFunc(this._Data[this._CurIndex]),
237
- this._Data[this._CurIndex]
238
- );
239
- this._SideEffect?.(item);
240
- this._CurIndex++;
241
- if (item[this._Key] >= (this._CurPage + 1) * this._PageRange) {
242
- this._CurPage++;
243
- }
244
- }
245
- if (added) {
246
- this._TemplateParser.CalculateNeighborWhenAddStop();
247
- }
248
- //再添加一屏
249
- this.tryAddItem(this._TemplateParser.GetItem(index), 2);
250
- }
251
-
252
- tryAddItemById(id) {
253
- const last_item = this._TemplateParser.GetItem(-1);
254
- if (!last_item || last_item.id < id) {
255
- let added = false;
256
- let item = last_item;
257
- while (!item || item.id < id) {
258
- added = true;
259
- item = this._TemplateParser.ParseTemplateItem(
260
- this._MeasureFunc(this._Data[this._CurIndex]),
261
- this._Data[this._CurIndex]
262
- );
263
- this._SideEffect?.(item);
264
- if (item[this._Key] >= (this._CurPage + 1) * this._PageRange) {
265
- this._CurPage++;
266
- }
267
- this._CurIndex++;
268
- }
269
- if (added) {
270
- this._TemplateParser.CalculateNeighborWhenAddStop();
271
- }
272
- }
273
- //再添加一屏
274
- this.tryAddItem(this._TemplateParser.GetItemById(id), 2);
275
- }
276
-
277
- updateData(data) {
278
- this._Data = data;
279
- }
280
- }
281
-
282
- class ItemRange {
283
- constructor(start, end) {
284
- this.start = start;
285
- this.end = end;
286
- }
287
-
288
- _merge(from, to) {
289
- if (to.ifOverlap(from)) {
290
- to.start = Math.min(from.start, to.start);
291
- to.end = Math.max(from.end, to.end);
292
- return true;
293
- }
294
- return false;
295
- }
296
-
297
- merge(from) {
298
- let to = this.clone();
299
- this._merge(from, to);
300
- return to;
301
- }
302
-
303
- selfMerge(from) {
304
- return this._merge(from, this);
305
- }
306
-
307
- ifOverlap(range) {
308
- return this.start <= range.end && range.start <= this.end;
309
- }
310
-
311
- clone() {
312
- return new ItemRange(this.start, this.end);
313
- }
314
- }
315
-
316
- function mergeRangeList(list_1, list_2) {
317
- const result_list = list_1.concat();
318
- for (let list_2_item of list_2) {
319
- let item = list_2_item.clone();
320
- for (let i = result_list.length - 1; i >= 0; i--) {
321
- if (item.selfMerge(result_list[i])) {
322
- result_list.splice(i, 1);
323
- }
324
- }
325
- result_list.push(item);
326
- }
327
- return result_list;
328
- }
329
-
330
- class PageUpdater {
331
- constructor(update_func) {
332
- this.tmpRangeList = [];
333
- this.rangeList = [];
334
-
335
- this._updateFunc = update_func;
336
- }
337
-
338
- update(
339
- template,
340
- visible_start,
341
- visible_end,
342
- anchor_id,
343
- merge_tmp,
344
- permanent_list
345
- ) {
346
- if (!template || template.GetLength() === 0) return;
347
- let visible_range = template.GetVisibleItemList(
348
- visible_start,
349
- visible_end,
350
- anchor_id
351
- );
352
- if (!visible_range) {
353
- return;
354
- }
355
- let pre_tmp = this.tmpRangeList;
356
- let pre_list = this.rangeList;
357
- let range = new ItemRange(
358
- visible_range.visibleStart,
359
- visible_range.visibleEnd
360
- );
361
- this.rangeList = [range];
362
- if (permanent_list) {
363
- let permanent_show_list = permanent_list.filter((item) => {
364
- let result = false;
365
- if (item.alreadyShow || item.index <= range.end) {
366
- item.alreadyShow = true;
367
- result = true;
368
- }
369
- return result;
370
- });
371
- let permanent_range_list = permanent_show_list.map((item) => {
372
- return new ItemRange(item.index, item.index);
373
- });
374
- this.rangeList = mergeRangeList([range], permanent_range_list);
375
- }
376
- if (pre_list.length > 0) {
377
- this.tmpRangeList = mergeRangeList(this.rangeList, pre_list);
378
- if (merge_tmp) {
379
- this.tmpRangeList = mergeRangeList(this.tmpRangeList, pre_tmp);
380
- }
381
- }
382
- }
383
-
384
- debugPrint() {
385
- return (
386
- "list: " +
387
- JSON.stringify(this.rangeList) +
388
- ", tmplist: " +
389
- JSON.stringify(this.tmpRangeList)
390
- );
391
- }
392
-
393
- apply() {
394
- this.tmpRangeList = [];
395
- this._updateFunc(this.rangeList);
396
- }
397
-
398
- applyTmp() {
399
- if (this.tmpRangeList.length > 0) {
400
- this._updateFunc(this.tmpRangeList);
401
- }
402
- }
403
-
404
- getRange() {
405
- return this.rangeList[0];
406
- }
407
- }
186
+ import { bindFunctions } from "./ToolFunctions";
408
187
 
409
188
  const _getPadding = function (padding) {
410
- let result = {
411
- left: 0,
412
- right: 0,
413
- top: 0,
414
- bottom: 0,
415
- };
416
-
417
- if (typeof padding !== "undefined" && padding !== null) {
418
- Object.assign(result, padding);
419
- }
420
- return result;
189
+ return Object.assign(
190
+ {
191
+ left: 0,
192
+ right: 0,
193
+ top: 0,
194
+ bottom: 0,
195
+ },
196
+ padding
197
+ );
421
198
  };
422
199
 
423
200
  const _getTemplateParser = function (
@@ -477,1509 +254,1631 @@ const directionFreeKeyMap = {
477
254
  },
478
255
  };
479
256
 
480
- const defaultSlideSetting = new SeamlessSlide(0.2, 0.8);
481
- const MetroWidget = {
482
- components: { RootView },
483
- props: {
484
- padding: {
485
- type: Object,
486
- default() {
487
- return {
488
- top: 0,
489
- left: 0,
490
- right: 0,
491
- bottom: 0,
492
- };
493
- },
494
- },
495
- direction: {
496
- type: Symbol,
497
- default: HORIZONTAL,
498
- },
499
- height: {
500
- type: Number,
501
- required: true,
502
- },
503
- width: {
504
- type: Number,
505
- required: true,
506
- },
507
- slideBoundary: {
508
- validator(value) {
509
- return !isNaN(value) && value < 0.5;
510
- },
511
- default: 0.2,
512
- },
513
- onClick: {
514
- type: Function,
515
- default: emptyFunc,
516
- },
517
- loopFocus: {
518
- type: Boolean,
519
- default: false,
520
- },
521
- onEdge: {
522
- type: Function,
523
- default: emptyFunc,
524
- },
525
- onFocus: {
526
- type: Function,
527
- default: emptyFunc,
528
- },
529
- onBlur: {
530
- type: Function,
531
- default: emptyFunc,
532
- },
533
- loadAll: {
534
- type: Boolean,
535
- default: false,
536
- },
537
- enableTouch: {
538
- type: Boolean,
539
- default: false,
540
- },
541
- flingPageWidth: {
542
- type: Number,
543
- default: -1,
544
- },
545
- flingPageEdge: {
546
- type: Number,
547
- default: 1 / 4,
548
- },
549
- dispatcher: {
550
- type: Object,
551
- },
552
- measures: {
553
- type: Function,
554
- required: true,
555
- },
556
- baseAnchor: {
557
- type: Object,
558
- },
559
- initFocusId: {
560
- type: Number,
561
- default: 0,
562
- },
563
- data: {
564
- type: Array,
565
- },
566
- left: {
567
- type: Number,
568
- default: 0,
569
- },
570
- top: {
571
- type: Number,
572
- default: 0,
573
- },
574
- name: {
575
- type: String,
576
- },
577
- supportHistoryPath: {
578
- type: Boolean,
579
- default: true,
580
- },
581
- itemConfig: {
582
- type: Function,
583
- },
584
- onFocusChange: {
585
- type: Function,
586
- },
587
- slideSetting: {
588
- type: SlideSetting,
589
- default: defaultSlideSetting,
590
- },
591
- layoutType: {
592
- type: String,
593
- default: "relative",
594
- },
595
- enableItemRenderBreak: {
596
- type: Boolean,
597
- default: false,
598
- },
599
- provideData: {
600
- type: Function,
601
- },
602
- placeHolderSetting: {
603
- type: Object,
604
- },
605
- sendFocusRectEvent: {
606
- type: Boolean,
607
- default: false,
257
+ const props = defineProps({
258
+ padding: {
259
+ type: Object,
260
+ default() {
261
+ return {
262
+ top: 0,
263
+ left: 0,
264
+ right: 0,
265
+ bottom: 0,
266
+ };
608
267
  },
609
268
  },
610
- watch: {
611
- data: function (value, oldValue) {
612
- console.log("watch data change ", value, oldValue);
269
+ direction: {
270
+ type: Symbol,
271
+ default: HORIZONTAL,
272
+ },
273
+ height: {
274
+ type: Number,
275
+ required: true,
276
+ },
277
+ width: {
278
+ type: Number,
279
+ required: true,
280
+ },
281
+ loopFocus: {
282
+ type: Boolean,
283
+ default: false,
284
+ },
285
+ onEdge: {
286
+ type: Function,
287
+ default: null,
288
+ },
289
+ onFocus: {
290
+ type: Function,
291
+ default: null,
292
+ },
293
+ onBlur: {
294
+ type: Function,
295
+ default: null,
296
+ },
297
+ loadAll: {
298
+ type: Boolean,
299
+ default: false,
300
+ },
301
+ enableTouch: {
302
+ type: Boolean,
303
+ default: false,
304
+ },
305
+ flingPageWidth: {
306
+ type: Number,
307
+ default: -1,
308
+ },
309
+ flingPageEdge: {
310
+ type: Number,
311
+ default: 1 / 4,
312
+ },
313
+ dispatcher: {
314
+ type: Object,
315
+ },
316
+ measures: {
317
+ type: Function,
318
+ required: true,
319
+ },
320
+ initFocusId: {
321
+ type: Number,
322
+ default: 0,
323
+ },
324
+ data: {
325
+ type: Array,
326
+ },
327
+ left: {
328
+ type: Number,
329
+ default: 0,
330
+ },
331
+ top: {
332
+ type: Number,
333
+ default: 0,
334
+ },
335
+ name: {
336
+ type: String,
337
+ },
338
+ supportHistoryPath: {
339
+ type: Boolean,
340
+ default: true,
341
+ },
342
+ itemConfig: {
343
+ type: Function,
344
+ },
345
+ onFocusChange: {
346
+ type: Function,
347
+ },
348
+ slideSetting: {
349
+ type: SlideSetting,
350
+ default() {
351
+ return new SeamlessSlide(0.2, 0.8);
613
352
  },
614
353
  },
615
- setup(props) {
616
- return {
617
- refreshToken: ref(0),
618
- dataUpdateToken: 0,
619
- templateParser: null,
620
- innerData: [],
621
- dataList: [],
622
- pageUpdater: null,
623
-
624
- enterFocusId: -1,
625
- enterFocusRect: null,
626
- focusId: 0,
627
- preFocusId: -1,
628
- preEdgeRect: null,
629
- isFocus: false,
630
- perAnchor: null,
631
- rootElement: null,
632
-
633
- visibleStart: 0,
634
- visibleRange: 0,
635
- visibleRangeWithPadding: 0,
636
-
637
- touchContainerW: ref(0),
638
- touchContainerH: ref(0),
639
- touchListener: null,
640
- innerPadding: null,
641
- slidePile: null,
642
- dragDirection: Forge.DragSetting.DIRECTION_HORIZONTAL,
643
- vertical: props.direction == VERTICAL,
644
- preAnchorItemIndex: -1,
645
- templateItemAdder: null,
646
- itemRender: ref(false),
647
- permanentItemList: [],
648
- preUpdateVisibleStart: 0,
649
-
650
- updateTimerHandler: -1,
651
- mounted: false,
652
- };
354
+ layoutType: {
355
+ type: String,
356
+ default: "relative",
357
+ },
358
+ enableItemRenderBreak: {
359
+ type: Boolean,
360
+ default: false,
653
361
  },
654
- methods: {
655
- //供外部获取SimpleWidget内部状态
656
- _injectHandler() {
362
+ provideData: {
363
+ type: Function,
364
+ },
365
+ placeHolderSetting: {
366
+ type: Object,
367
+ default() {
657
368
  return {
658
- getPosition: this._getPosition,
659
- getTemplatePosition: this._getTemplatePosition,
660
- getAbsolutePosition: this._getAbsolutePosition,
661
- registerItemFunc: this._registerItemFunc,
662
- getCurrentFocusId: this._getCurrentId,
663
- isFocus: this._isFocus,
664
- customerSlide: this.slideTo,
665
- updateMounted: this._updateMounted,
666
- registerItemRef: this._registerItemRef,
667
- onFocusChange: this._onFocusChange,
668
- getPreEdgeRect: this._getPreEdgeRect,
669
- sendCustomerEvent: this._bubbleCustomerEvent,
670
- handler: this,
369
+ backgroundColor: "rgba(255,255,255,0.5)",
671
370
  };
672
371
  },
372
+ },
373
+ sendFocusRectEvent: {
374
+ type: Boolean,
375
+ default: false,
376
+ },
377
+ keepTraceRange: {
378
+ type: Number,
379
+ default: 0,
380
+ },
381
+ onScroll: {
382
+ type: Function,
383
+ },
384
+ });
385
+
386
+ let dataUpdateToken = ref(0);
387
+ let templateParser = null;
388
+ let innerData = [];
389
+ let dataList = [];
390
+ let pageUpdater = null;
391
+ let enterFocusId = -1;
392
+ let enterFocusRect = null;
393
+ let focusId = 0;
394
+ let preFocusId = -1;
395
+ let preEdgeRect = null;
396
+ let isFocus = false;
397
+ let touchContainerW = ref(0);
398
+ let touchContainerH = ref(0);
399
+ let touchListener = null;
400
+ let innerPadding = null;
401
+ let slidePile = null;
402
+ let dragDirection = Forge.DragSetting.DIRECTION_HORIZONTAL;
403
+ let vertical = props.direction == VERTICAL;
404
+ let preAnchorItemIndex = -1;
405
+ let templateItemAdder = null;
406
+ let itemRender = ref(!props.enableItemRenderBreak);
407
+ let permanentItemList = [];
408
+ let preUpdateVisibleStart = 0;
409
+ let mounted = false;
410
+ let focusNode = ref(null);
411
+ let pageRange = vertical ? props.height : props.width;
412
+ let visibleInfo = {
413
+ _start: 0,
414
+ range: 0,
415
+ padding: {
416
+ start: 0,
417
+ end: 0,
418
+ },
419
+ _startMax: 0,
673
420
 
674
- _getPreEdgeRect() {
675
- return this.preEdgeRect;
676
- },
421
+ set start(value) {
422
+ this._start = value;
423
+ this._startMax = Math.max(this._start, this._startMax);
424
+ },
677
425
 
678
- _onFocusChange(id) {
679
- this.onFocusChange?.(id);
680
- },
426
+ get start() {
427
+ return this._start;
428
+ },
681
429
 
682
- _isFocus() {
683
- return this.isFocus;
684
- },
430
+ get end() {
431
+ return this._start + this.range - 1;
432
+ },
685
433
 
686
- _getCurrentId() {
687
- return {
688
- id: this.focusId,
689
- index: this.templateParser.FocusIdToIndex(this.focusId),
690
- };
691
- },
434
+ get startMax() {
435
+ return this._startMax;
436
+ },
692
437
 
693
- _registerItemFunc(index, handlerObj) {
694
- this.innerData[index].itemHandler = handlerObj;
695
- },
438
+ get startWithPadding() {
439
+ return this._start - this.padding.start;
440
+ },
696
441
 
697
- _registerItemRef(index, itemRef) {
698
- this.innerData[index].itemRef = itemRef;
699
- },
442
+ get endWithPadding() {
443
+ return this._start + this.range + this.padding.end - 1;
444
+ },
445
+ };
700
446
 
701
- _updateMounted(index, mounted) {
702
- if (index >= this.innerData.length) {
703
- console.warn("sw updateMounted error: over range");
704
- return;
705
- }
706
- this.innerData[index].mounted = mounted;
707
- },
447
+ let locateDiv = ref(null);
448
+ let slideDiv = ref(null);
449
+ let renderData = shallowRef([]);
450
+ let slideDivLeft = ref(0);
451
+ let slideDivTop = ref(0);
452
+ let callFocusAfterUpdate = false;
453
+ let renderBreakKey = props.enableItemRenderBreak
454
+ ? "__QcodeJsviewMetroWidgetSlot"
455
+ : "";
456
+ let pageUpdateToken = ref(0);
457
+
458
+ //methods
459
+ const _onFocusChange = (id) => {
460
+ props.onFocusChange?.(id);
461
+ };
708
462
 
709
- _getPosition(index) {
710
- let item = this.templateParser.GetItem(index);
711
- let x_offset = this.direction === VERTICAL ? 0 : -this.visibleStart;
712
- let y_offset = this.direction === VERTICAL ? -this.visibleStart : 0;
713
- return {
714
- left: item.xPos + x_offset,
715
- top: item.yPos + y_offset,
716
- width: item.width,
717
- height: item.height,
718
- };
719
- },
463
+ const _getCurrentId = () => {
464
+ return {
465
+ id: focusId,
466
+ index: templateParser.FocusIdToIndex(focusId),
467
+ };
468
+ };
720
469
 
721
- _getTemplatePosition(index) {
722
- let item = this.templateParser.GetItem(index);
723
- return {
724
- left: item.xPos,
725
- top: item.yPos,
726
- width: item.width,
727
- height: item.height,
728
- };
729
- },
470
+ const _getPosition = (index) => {
471
+ let item = templateParser.GetItem(index);
472
+ let x_offset = props.direction === VERTICAL ? 0 : -visibleInfo.start;
473
+ let y_offset = props.direction === VERTICAL ? -visibleInfo.start : 0;
474
+ return {
475
+ left: item.xPos + x_offset,
476
+ top: item.yPos + y_offset,
477
+ width: item.width,
478
+ height: item.height,
479
+ };
480
+ };
730
481
 
731
- _getAbsolutePosition(index, targetEle) {
732
- return getPositionRelativeToView(
733
- this.innerData[index].itemRef?.getDivElement(),
734
- targetEle
735
- );
736
- },
482
+ const _getTemplatePosition = (index) => {
483
+ let item = templateParser.GetItem(index);
484
+ return {
485
+ left: item.xPos,
486
+ top: item.yPos,
487
+ width: item.width,
488
+ height: item.height,
489
+ };
490
+ };
737
491
 
738
- _dispatchEvent(event) {
739
- switch (event.type) {
740
- case Dispatcher.Type.setEnterFocusId:
741
- this.setEnterFocusId(event.data);
742
- break;
743
- case Dispatcher.Type.setEnterFocusRect:
744
- this.setEnterFocusRect(event.data);
745
- break;
746
- case Dispatcher.Type.updateItem:
747
- break;
748
- case Dispatcher.Type.slideToItem:
749
- if (event.data) {
750
- this.slideToItem(event.data?.id, event.data?.doAnim);
751
- }
752
- break;
753
- case Dispatcher.Type.setFocusId:
754
- this.setFocusId(
755
- event.data?.id,
756
- event.data?.needSlide,
757
- event.data?.doAnim
758
- );
759
- break;
760
- default:
761
- break;
492
+ const _getAbsolutePosition = (index, targetEle) => {
493
+ return getPositionRelativeToView(innerData[index].itemDivRef, targetEle);
494
+ };
495
+
496
+ const _dispatchEvent = (event) => {
497
+ switch (event.type) {
498
+ case Dispatcher.Type.setEnterFocusId:
499
+ setEnterFocusId(event.data);
500
+ break;
501
+ case Dispatcher.Type.setEnterFocusRect:
502
+ setEnterFocusRect(event.data);
503
+ break;
504
+ case Dispatcher.Type.updateItem:
505
+ break;
506
+ case Dispatcher.Type.slideToItem:
507
+ if (event.data) {
508
+ slideToItem(event.data?.id, event.data?.doAnim);
762
509
  }
763
- },
510
+ break;
511
+ case Dispatcher.Type.setFocusId:
512
+ setFocusId(event.data?.id, event.data?.needSlide, event.data?.doAnim);
513
+ break;
514
+ default:
515
+ break;
516
+ }
517
+ };
764
518
 
765
- setFocusId(id, needSlide = true, doAnim = false) {
766
- this.templateItemAdder.tryAddItemById(id);
767
- let next_focus_item = this.templateParser.GetItemById(id);
768
- if (next_focus_item) {
769
- if (needSlide) {
770
- this.slideToItem(this.templateParser.FocusIdToIndex(id), doAnim);
771
- }
519
+ const onItemClick = (index) => {
520
+ if (isFocus && innerData[index].callbacks.callable("onClick")) {
521
+ innerData[index].callbacks.onClick();
522
+ }
523
+ };
772
524
 
773
- const cur_focus_item = this.templateParser.GetItemById(this.focusId);
774
- this.preFocusId = this.focusId;
775
- this.focusId = next_focus_item.id;
776
-
777
- let x_off_set = cur_focus_item.xPos - next_focus_item.xPos;
778
- let y_off_set = cur_focus_item.yPos - next_focus_item.yPos;
779
- this.preEdgeRect = {
780
- direction: null,
781
- rect: {
782
- x: x_off_set,
783
- y: y_off_set,
784
- width: cur_focus_item.width,
785
- height: cur_focus_item.height,
786
- },
787
- };
788
- this._updateBlurItem();
789
- this._updateFocusItem();
790
- if (this.isFocus) {
791
- this.innerData[
792
- this.templateParser.FocusIdToIndex(this.preFocusId)
793
- ].itemHandler.onBlur?.();
794
- }
795
- if (
796
- this.isFocus &&
797
- this.innerData[this.templateParser.FocusIdToIndex(this.focusId)]
798
- .mounted
799
- ) {
800
- this.innerData[
801
- this.templateParser.FocusIdToIndex(this.focusId)
802
- ].itemHandler.onFocus?.(this.preEdgeRect);
803
- }
804
- }
805
- },
525
+ const onItemBlur = (index) => {
526
+ if (isFocus && innerData[index].callbacks.callable("onBlur")) {
527
+ innerData[index].callbacks.onBlur();
528
+ }
529
+ };
806
530
 
807
- getFocusBlockRef() {
808
- return this.$refs.focusNode;
809
- },
531
+ const onItemFocus = (index, rect) => {
532
+ if (isFocus) {
533
+ _itemOnFocusSideEffect(innerData[index], rect);
534
+ if (innerData[index].callbacks.callable("onFocus")) {
535
+ innerData[index].callbacks.onFocus(rect);
536
+ } else {
537
+ callFocusAfterUpdate = true;
538
+ }
539
+ }
540
+ };
810
541
 
811
- setEnterFocusId(id) {
812
- this.templateItemAdder.tryAddItemById(id);
813
- this.enterFocusId = id;
814
- },
542
+ const setFocusId = (id, needSlide = true, doAnim = false) => {
543
+ templateItemAdder.tryAddItemById(id);
544
+ let next_focus_item = templateParser.GetItemById(id);
545
+ if (next_focus_item) {
546
+ if (needSlide) {
547
+ slideToItem(templateParser.FocusIdToIndex(id), doAnim);
548
+ }
815
549
 
816
- setEnterFocusRect(rect) {
817
- this.enterFocusRect = rect;
818
- },
550
+ const cur_focus_item = templateParser.GetItemById(focusId);
551
+ preFocusId = focusId;
552
+ focusId = next_focus_item.id;
553
+
554
+ let x_off_set = cur_focus_item.xPos - next_focus_item.xPos;
555
+ let y_off_set = cur_focus_item.yPos - next_focus_item.yPos;
556
+ preEdgeRect = {
557
+ direction: null,
558
+ rect: {
559
+ x: x_off_set,
560
+ y: y_off_set,
561
+ width: cur_focus_item.width,
562
+ height: cur_focus_item.height,
563
+ },
564
+ };
565
+ _updateBlurItem();
566
+ _updateFocusItem();
567
+ onItemBlur(templateParser.FocusIdToIndex(preFocusId));
568
+ onItemFocus(templateParser.FocusIdToIndex(focusId), preEdgeRect);
569
+ }
570
+ };
819
571
 
820
- slideTo(position, doAnim) {
821
- this.templateItemAdder.tryAddItemByPosition(position);
822
- if (
823
- typeof position !== "undefined" &&
824
- position != null &&
825
- this.visibleStart !== position
826
- ) {
827
- this.visibleStart = position;
828
- let animObj = null;
829
- if (doAnim) {
830
- animObj = {
831
- easing: this.slideSetting.Easing,
832
- onstart: null,
833
- speed: this.slideSetting.Speed,
834
- onend: this._onSlideEnd,
835
- };
836
- }
837
- this._slideTo(this.visibleStart, animObj);
838
-
839
- this.pageUpdater.update(
840
- this.templateParser,
841
- this.visibleStart,
842
- this.visibleStart + this.visibleRangeWithPadding - 1,
843
- this.focusId,
844
- false,
845
- this.permanentItemList
846
- );
847
- if (doAnim) {
848
- this.pageUpdater.applyTmp();
849
- } else {
850
- this.pageUpdater.apply();
851
- }
852
- }
853
- },
572
+ const getFocusBlockRef = () => {
573
+ return toRaw(focusNode.value);
574
+ };
854
575
 
855
- slideToItem(index, doAnim) {
856
- this.templateItemAdder.tryAddItemByIndex(index);
857
- const targetItem = this.templateParser.GetItem(index);
858
- if (targetItem) {
859
- const direction = index - this.preAnchorItemIndex > 0 ? 1 : -1;
860
- const visible_start = this._calculateVisibleStart(
861
- targetItem,
862
- direction
863
- );
864
- this.slideTo(visible_start, doAnim);
865
- }
866
- },
576
+ const setEnterFocusId = (id) => {
577
+ templateItemAdder.tryAddItemById(id);
578
+ enterFocusId = id;
579
+ };
867
580
 
868
- refreshData(force_update) {
869
- //由于data不支持reactive, 因此数据的更新只通过provideData
870
- if (!this.provideData) {
871
- console.error("refreshData: provideData is null.");
872
- return;
873
- }
874
- let _force_update = force_update;
875
- let template_list = this.templateParser.GetTemplate().List;
876
- if (!template_list || template_list.length === 0) {
877
- _force_update = true;
878
- }
879
- let new_list = this.provideData();
880
- if (this.focusId >= new_list.length) {
881
- this.focusId = 0;
882
- this.preFocusId = -1;
883
- if (this.visibleStart !== 0) {
884
- this.visibleStart = 0;
885
- this._slideTo(0, null);
886
- }
887
- }
888
- let new_index = 0;
889
- if (!_force_update) {
890
- for (new_index = 0; new_index < new_list.length; ++new_index) {
891
- let already_add = false;
892
- for (let j = 0; j < template_list.length; ++j) {
893
- if (new_list[new_index] === template_list[j].data) {
894
- already_add = true;
895
- break;
896
- }
897
- }
898
- if (!already_add) {
899
- break;
900
- }
901
- }
902
- }
903
- let need_update_content = false;
904
- if (!_force_update && new_index === template_list.length) {
905
- //原始数据都在
906
- if (new_index !== new_list.length) {
907
- //增加数据
908
- need_update_content = true;
909
- this.templateItemAdder.updateData(new_list);
910
- } else {
911
- //数据没变
581
+ const setEnterFocusRect = (rect) => {
582
+ enterFocusRect = rect;
583
+ };
584
+
585
+ const slideTo = (position, doAnim) => {
586
+ templateItemAdder.tryAddItemByPosition(position);
587
+ if (
588
+ typeof position !== "undefined" &&
589
+ position != null &&
590
+ visibleInfo.start !== position
591
+ ) {
592
+ visibleInfo.start = position;
593
+ let animObj = null;
594
+ if (doAnim) {
595
+ animObj = {
596
+ easing: props.slideSetting.Easing,
597
+ onstart: null,
598
+ speed: props.slideSetting.Speed,
599
+ onend: _onSlideEnd,
600
+ };
601
+ }
602
+ _slideTo(visibleInfo.start, animObj);
603
+
604
+ pageUpdater.update(
605
+ templateParser,
606
+ visibleInfo.startWithPadding,
607
+ visibleInfo.endWithPadding,
608
+ focusId,
609
+ false,
610
+ permanentItemList
611
+ );
612
+ if (doAnim) {
613
+ pageUpdater.applyTmp();
614
+ } else {
615
+ pageUpdater.apply();
616
+ }
617
+ }
618
+ };
619
+
620
+ const slideToItem = (index, doAnim) => {
621
+ templateItemAdder.tryAddItemByIndex(index);
622
+ const targetItem = templateParser.GetItem(index);
623
+ if (targetItem) {
624
+ const direction = index - preAnchorItemIndex > 0 ? 1 : -1;
625
+ const visible_start = _calculateVisibleStart(targetItem, direction);
626
+ slideTo(visible_start, doAnim);
627
+ }
628
+ };
629
+
630
+ const refreshData = (force_update) => {
631
+ //由于data不支持reactive, 因此数据的更新只通过provideData
632
+ if (!props.provideData) {
633
+ console.error("refreshData: provideData is null.");
634
+ return;
635
+ }
636
+ let _force_update = force_update;
637
+ let template_list = templateParser.GetTemplate().List;
638
+ if (!template_list || template_list.length === 0) {
639
+ _force_update = true;
640
+ }
641
+ let new_list = toRaw(props.provideData());
642
+ let needSlide = false;
643
+ if (focusId >= new_list.length) {
644
+ focusId = 0;
645
+ preFocusId = -1;
646
+ if (visibleInfo.start !== 0) {
647
+ visibleInfo.start = 0;
648
+ needSlide = true;
649
+ }
650
+ }
651
+ let new_index = 0;
652
+ if (!_force_update) {
653
+ for (new_index = 0; new_index < new_list.length; ++new_index) {
654
+ let already_add = false;
655
+ for (let j = 0; j < template_list.length; ++j) {
656
+ if (new_list[new_index] === template_list[j].data) {
657
+ already_add = true;
658
+ break;
912
659
  }
913
- } else {
914
- //数据更改
915
- this.permanentItemList = [];
916
- need_update_content = true;
917
- this.templateParser = _getTemplateParser(
918
- this.width,
919
- this.height,
920
- this.direction,
921
- this.padding,
922
- this.supportHistoryPath,
923
- this.layoutType
924
- );
925
- this.innerData = [];
926
- this.dataList = new_list;
927
- this.templateItemAdder = new TemplateItemAdder(
928
- this.templateParser,
929
- new_list,
930
- this.measures,
931
- this.visibleRangeWithPadding,
932
- this._onTemplateAdd
933
- );
934
- this.templateItemAdder.tryAddItemById(this.focusId);
935
660
  }
936
- if (need_update_content) {
937
- let template_list = this.templateParser.GetTemplate().List;
938
- let last_item = template_list[template_list.length - 1];
939
- this.touchListener = this._getTouchListener();
940
- this.innerPadding = _getPadding(this.padding);
941
- this.touchContainerW =
942
- this.direction === VERTICAL
943
- ? this.width
944
- : last_item.xPos + last_item.width;
945
- this.touchContainerH =
946
- this.direction === VERTICAL
947
- ? last_item.yPos + last_item.height
948
- : this.height;
949
- this.slidePile = new Forge.RectArea(
950
- 0,
951
- 0,
952
- this.width - this.innerPadding.left - this.innerPadding.right,
953
- this.height - this.innerPadding.top - this.innerPadding.bottom
954
- );
955
- this.dragDirection =
956
- this.direction === VERTICAL
957
- ? Forge.DragSetting.DIRECTION_VERTICAL
958
- : Forge.DragSetting.DIRECTION_HORIZONTAL;
661
+ if (!already_add) {
662
+ break;
959
663
  }
960
- this.pageUpdater.update(
961
- this.templateParser,
962
- this.visibleStart,
963
- this.visibleStart + this.visibleRangeWithPadding - 1,
964
- this.focusId,
965
- false,
966
- this.permanentItemList
967
- );
968
- this.dataUpdateToken++;
969
- this.pageUpdater.apply();
970
- if (
971
- this.isFocus &&
972
- this.innerData[this.templateParser.FocusIdToIndex(this.focusId)].mounted
973
- ) {
974
- this._updateFocusItem();
975
- this.innerData[
976
- this.templateParser.FocusIdToIndex(this.focusId)
977
- ].itemHandler.onFocus?.(null);
978
- }
979
- },
664
+ }
665
+ }
666
+ let need_update_content = false;
667
+ if (!_force_update && new_index === template_list.length) {
668
+ //原始数据都在
669
+ if (new_index !== new_list.length) {
670
+ //增加数据
671
+ need_update_content = true;
672
+ templateItemAdder.updateData(new_list);
673
+ } else {
674
+ //数据没变
675
+ }
676
+ } else {
677
+ pageUpdateToken.value++;
678
+ //数据更改
679
+ permanentItemList = [];
680
+ need_update_content = true;
681
+ templateParser = _getTemplateParser(
682
+ props.width,
683
+ props.height,
684
+ props.direction,
685
+ props.padding,
686
+ props.supportHistoryPath,
687
+ props.layoutType
688
+ );
689
+ innerData = [];
690
+ dataList = new_list;
691
+ templateItemAdder = new TemplateItemAdder(
692
+ templateParser,
693
+ dataList,
694
+ props.measures,
695
+ pageRange,
696
+ _onTemplateAdd
697
+ );
698
+ }
699
+ if (need_update_content) {
700
+ if (props.onScroll) {
701
+ templateItemAdder.tryAddItemByIndex(dataList.length - 1);
702
+ } else {
703
+ templateItemAdder.tryAddItemById(focusId);
704
+ }
705
+ let template_list = templateParser.GetTemplate().List;
706
+ let last_item = template_list[template_list.length - 1];
707
+ touchListener = _getTouchListener();
708
+ innerPadding = _getPadding(props.padding);
709
+ touchContainerW.value =
710
+ props.direction === VERTICAL
711
+ ? props.width
712
+ : last_item
713
+ ? last_item.xPos + last_item.width
714
+ : 0;
715
+ touchContainerH.value =
716
+ props.direction === VERTICAL
717
+ ? last_item
718
+ ? last_item.yPos + last_item.height
719
+ : 0
720
+ : props.height;
721
+ slidePile = new Forge.RectArea(
722
+ 0,
723
+ 0,
724
+ props.width - innerPadding.left - innerPadding.right,
725
+ props.height - innerPadding.top - innerPadding.bottom
726
+ );
727
+ dragDirection =
728
+ props.direction === VERTICAL
729
+ ? Forge.DragSetting.DIRECTION_VERTICAL
730
+ : Forge.DragSetting.DIRECTION_HORIZONTAL;
731
+ }
732
+ pageUpdater.update(
733
+ templateParser,
734
+ visibleInfo.startWithPadding,
735
+ visibleInfo.endWithPadding,
736
+ focusId,
737
+ false,
738
+ permanentItemList
739
+ );
740
+ dataUpdateToken.value++;
741
+ pageUpdater.apply();
742
+ _updateFocusItem();
743
+ onItemFocus(templateParser.FocusIdToIndex(focusId), null);
744
+ if (needSlide) {
745
+ _slideTo(visibleInfo.start, null);
746
+ } else if (need_update_content) {
747
+ _onScroll();
748
+ }
749
+ };
750
+
751
+ const exportObject = {
752
+ slideTo,
753
+ setFocusId,
754
+ getFocusBlockRef,
755
+ setEnterFocusId,
756
+ setEnterFocusRect,
757
+ slideToItem,
758
+ refreshData,
759
+ _dispatchEvent,
760
+ _getAbsolutePosition,
761
+ };
980
762
 
981
- _calculateNearestItemByRect(visible_range, enter_rect_info) {
982
- let edge_direction = enter_rect_info.direction;
983
- let rect = enter_rect_info.rect;
984
- var direction = "";
985
- var point = { x: 0, y: 0 };
986
- switch (edge_direction) {
987
- case EdgeDirection.left:
988
- direction = "left";
989
- point.x = rect.x;
990
- point.y = rect.y + rect.height / 4;
763
+ const _calculateNearestItemByRect = (visible_range, enter_rect_info) => {
764
+ let edge_direction = enter_rect_info.direction;
765
+ let rect = enter_rect_info.rect;
766
+ var direction = "";
767
+ var point = { x: 0, y: 0 };
768
+ switch (edge_direction) {
769
+ case EdgeDirection.left:
770
+ direction = "left";
771
+ point.x = rect.x;
772
+ point.y = rect.y + rect.height / 4;
773
+ break;
774
+ case EdgeDirection.right:
775
+ direction = "right";
776
+ point.x = rect.x + rect.width;
777
+ point.y = rect.y + rect.height / 4;
778
+ break;
779
+ case EdgeDirection.top:
780
+ direction = "up";
781
+ point.x = rect.x + rect.width / 4;
782
+ point.y = rect.y;
783
+ break;
784
+ case EdgeDirection.bottom:
785
+ direction = "down";
786
+ point.x = rect.x + rect.width / 4;
787
+ point.y = rect.y + rect.height;
788
+ break;
789
+ default:
790
+ break;
791
+ }
792
+
793
+ var src_x_range = new SingleRangeModel(point.x, point.x);
794
+ var src_y_range = new SingleRangeModel(point.y, point.y);
795
+
796
+ var min_distance_item = null;
797
+ var min_distance = -1;
798
+ var min_direction_weighted = 0;
799
+ var distance = 0;
800
+ var direction_weighted = 0; // 根据进入方向决定的权值,用于保证
801
+
802
+ let key_pos = props.direction === VERTICAL ? "yPos" : "xPos";
803
+ let key_width = props.direction === VERTICAL ? "height" : "width";
804
+ for (let index = visible_range.start; index <= visible_range.end; index++) {
805
+ let item = templateParser.GetItem(index);
806
+ if (!item.focusable) continue;
807
+ let full_show =
808
+ item[key_pos] >= visibleInfo.start &&
809
+ item[key_pos] + item[key_width] - 1 <= visibleInfo.end;
810
+ if (full_show) {
811
+ let x_pos =
812
+ props.direction === VERTICAL
813
+ ? item.xPos
814
+ : item.xPos - visibleInfo.start;
815
+ let y_pos =
816
+ props.direction === VERTICAL
817
+ ? item.yPos - visibleInfo.start
818
+ : item.yPos;
819
+ var target_x_range = new SingleRangeModel(x_pos, x_pos + item.width - 1);
820
+ var target_y_range = new SingleRangeModel(y_pos, y_pos + item.height - 1);
821
+ switch (direction) {
822
+ case "left":
823
+ if (point.x < x_pos + item.width - 1) {
824
+ // 这个点在item左侧,不可能左移到item
825
+ continue;
826
+ }
827
+ if (point.y < y_pos) {
828
+ //1.该点在其上,计算point和item右上角的距离
829
+ distance =
830
+ Math.pow(point.x - (x_pos + item.width - 1), 2) +
831
+ Math.pow(y_pos - point.y, 2);
832
+ } else if (src_y_range.IsInterAct(target_y_range)) {
833
+ //2.该点在其中,计算point和item右边框的垂直距离
834
+ distance = Math.pow(point.x - (x_pos + item.width - 1), 2);
835
+ } else if (point.y > y_pos + item.height - 1) {
836
+ //3.该点在其下,计算point到item右下角的距离
837
+ distance =
838
+ Math.pow(point.x - (x_pos + item.width - 1), 2) +
839
+ Math.pow(point.y - (y_pos + item.height - 1), 2);
840
+ }
841
+ // point与item右边框的距离作为权值
842
+ direction_weighted = Math.abs(point.x - (x_pos + item.width - 1));
991
843
  break;
992
- case EdgeDirection.right:
993
- direction = "right";
994
- point.x = rect.x + rect.width;
995
- point.y = rect.y + rect.height / 4;
844
+ case "right":
845
+ if (point.x > x_pos) {
846
+ // 这个点在item右侧,不可能右移到item
847
+ continue;
848
+ }
849
+ if (point.y < y_pos) {
850
+ //1.该点在其上, 计算point和item左上角的距离
851
+ distance =
852
+ Math.pow(x_pos - point.x, 2) + Math.pow(y_pos - point.y, 2);
853
+ } else if (src_y_range.IsInterAct(target_y_range)) {
854
+ //2.该点在其中,计算point和item左边框的垂直距离
855
+ distance = Math.pow(x_pos - point.x, 2);
856
+ //(x2-x1)^2
857
+ } else if (point.y > y_pos + item.height - 1) {
858
+ //3.该点在其下,计算point和item左下角的距离
859
+ distance =
860
+ Math.pow(x_pos - point.x, 2) +
861
+ Math.pow(point.y - (y_pos + item.height - 1), 2);
862
+ }
863
+ // point与item左边框的距离作为权值
864
+ direction_weighted = Math.abs(point.x - x_pos);
996
865
  break;
997
- case EdgeDirection.top:
998
- direction = "up";
999
- point.x = rect.x + rect.width / 4;
1000
- point.y = rect.y;
866
+ case "up":
867
+ if (point.y < y_pos + item.height - 1) {
868
+ // 这个点在item上侧,不可能上移到item
869
+ continue;
870
+ }
871
+ if (point.x < x_pos) {
872
+ //1.该点在其前,计算point和item右下角的距离
873
+ distance =
874
+ Math.pow(point.x - x_pos, 2) +
875
+ Math.pow(point.y - (y_pos + item.height - 1), 2);
876
+ } else if (src_x_range.IsInterAct(target_x_range)) {
877
+ //2.该点在其中,计算point和item下边框的垂直距离
878
+ distance = Math.pow(point.y - (y_pos + item.height - 1), 2);
879
+ } else if (point.x > x_pos + item.width - 1) {
880
+ //3.该点在其后,计算point和item左下角的距离
881
+ distance =
882
+ Math.pow(point.x - (x_pos + item.width - 1), 2) +
883
+ Math.pow(point.y - (y_pos + item.height - 1), 2);
884
+ }
885
+ // point与item下边框的距离作为权值
886
+ direction_weighted = Math.abs(point.y - (y_pos + item.height - 1));
1001
887
  break;
1002
- case EdgeDirection.bottom:
1003
- direction = "down";
1004
- point.x = rect.x + rect.width / 4;
1005
- point.y = rect.y + rect.height;
888
+ case "down":
889
+ if (point.y > y_pos) {
890
+ // 这个点在item下侧,不可能下移到item
891
+ continue;
892
+ }
893
+ if (point.x < x_pos) {
894
+ //1.该点在其前,计算point和item右上角的距离
895
+ distance =
896
+ Math.pow(point.x - x_pos, 2) + Math.pow(y_pos - point.y, 2);
897
+ } else if (src_x_range.IsInterAct(target_x_range)) {
898
+ //2.该点在其中,计算point和item上边框的垂直距离
899
+ distance = Math.pow(y_pos - point.y, 2);
900
+ } else if (point.x > x_pos + item.width - 1) {
901
+ //3.该点在其后,计算point和item左上角的距离
902
+ distance =
903
+ Math.pow(point.x - (x_pos + item.width - 1), 2) +
904
+ Math.pow(y_pos - point.y, 2);
905
+ }
906
+ // point与item上边框的距离作为权值
907
+ direction_weighted = Math.abs(point.y - y_pos);
1006
908
  break;
1007
909
  default:
910
+ console.log("direction is error:" + direction);
1008
911
  break;
1009
912
  }
1010
-
1011
- var src_x_range = new SingleRangeModel(point.x, point.x);
1012
- var src_y_range = new SingleRangeModel(point.y, point.y);
1013
-
1014
- var min_distance_item = null;
1015
- var min_distance = -1;
1016
- var min_direction_weighted = 0;
1017
- var distance = 0;
1018
- var direction_weighted = 0; // 根据进入方向决定的权值,用于保证
1019
-
1020
- let key_pos = this.direction === VERTICAL ? "yPos" : "xPos";
1021
- let key_width = this.direction === VERTICAL ? "height" : "width";
1022
- for (
1023
- let index = visible_range.start;
1024
- index <= visible_range.end;
1025
- index++
1026
- ) {
1027
- let item = this.templateParser.GetItem(index);
1028
- if (!item.focusable) continue;
1029
- let full_show =
1030
- item[key_pos] >= this.visibleStart &&
1031
- item[key_pos] + item[key_width] - 1 <=
1032
- this.visibleStart + this.visibleRange - 1;
1033
- if (full_show) {
1034
- let x_pos =
1035
- this.direction === VERTICAL
1036
- ? item.xPos
1037
- : item.xPos - this.visibleStart;
1038
- let y_pos =
1039
- this.direction === VERTICAL
1040
- ? item.yPos - this.visibleStart
1041
- : item.yPos;
1042
- var target_x_range = new SingleRangeModel(
1043
- x_pos,
1044
- x_pos + item.width - 1
1045
- );
1046
- var target_y_range = new SingleRangeModel(
1047
- y_pos,
1048
- y_pos + item.height - 1
1049
- );
1050
- switch (direction) {
1051
- case "left":
1052
- if (point.x < x_pos + item.width - 1) {
1053
- // 这个点在item左侧,不可能左移到item
1054
- continue;
1055
- }
1056
- if (point.y < y_pos) {
1057
- //1.该点在其上,计算point和item右上角的距离
1058
- distance =
1059
- Math.pow(point.x - (x_pos + item.width - 1), 2) +
1060
- Math.pow(y_pos - point.y, 2);
1061
- } else if (src_y_range.IsInterAct(target_y_range)) {
1062
- //2.该点在其中,计算point和item右边框的垂直距离
1063
- distance = Math.pow(point.x - (x_pos + item.width - 1), 2);
1064
- } else if (point.y > y_pos + item.height - 1) {
1065
- //3.该点在其下,计算point到item右下角的距离
1066
- distance =
1067
- Math.pow(point.x - (x_pos + item.width - 1), 2) +
1068
- Math.pow(point.y - (y_pos + item.height - 1), 2);
1069
- }
1070
- // point与item右边框的距离作为权值
1071
- direction_weighted = Math.abs(point.x - (x_pos + item.width - 1));
1072
- break;
1073
- case "right":
1074
- if (point.x > x_pos) {
1075
- // 这个点在item右侧,不可能右移到item
1076
- continue;
1077
- }
1078
- if (point.y < y_pos) {
1079
- //1.该点在其上, 计算point和item左上角的距离
1080
- distance =
1081
- Math.pow(x_pos - point.x, 2) + Math.pow(y_pos - point.y, 2);
1082
- } else if (src_y_range.IsInterAct(target_y_range)) {
1083
- //2.该点在其中,计算point和item左边框的垂直距离
1084
- distance = Math.pow(x_pos - point.x, 2);
1085
- //(x2-x1)^2
1086
- } else if (point.y > y_pos + item.height - 1) {
1087
- //3.该点在其下,计算point和item左下角的距离
1088
- distance =
1089
- Math.pow(x_pos - point.x, 2) +
1090
- Math.pow(point.y - (y_pos + item.height - 1), 2);
1091
- }
1092
- // point与item左边框的距离作为权值
1093
- direction_weighted = Math.abs(point.x - x_pos);
1094
- break;
1095
- case "up":
1096
- if (point.y < y_pos + item.height - 1) {
1097
- // 这个点在item上侧,不可能上移到item
1098
- continue;
1099
- }
1100
- if (point.x < x_pos) {
1101
- //1.该点在其前,计算point和item右下角的距离
1102
- distance =
1103
- Math.pow(point.x - x_pos, 2) +
1104
- Math.pow(point.y - (y_pos + item.height - 1), 2);
1105
- } else if (src_x_range.IsInterAct(target_x_range)) {
1106
- //2.该点在其中,计算point和item下边框的垂直距离
1107
- distance = Math.pow(point.y - (y_pos + item.height - 1), 2);
1108
- } else if (point.x > x_pos + item.width - 1) {
1109
- //3.该点在其后,计算point和item左下角的距离
1110
- distance =
1111
- Math.pow(point.x - (x_pos + item.width - 1), 2) +
1112
- Math.pow(point.y - (y_pos + item.height - 1), 2);
1113
- }
1114
- // point与item下边框的距离作为权值
1115
- direction_weighted = Math.abs(
1116
- point.y - (y_pos + item.height - 1)
1117
- );
1118
- break;
1119
- case "down":
1120
- if (point.y > y_pos) {
1121
- // 这个点在item下侧,不可能下移到item
1122
- continue;
1123
- }
1124
- if (point.x < x_pos) {
1125
- //1.该点在其前,计算point和item右上角的距离
1126
- distance =
1127
- Math.pow(point.x - x_pos, 2) + Math.pow(y_pos - point.y, 2);
1128
- } else if (src_x_range.IsInterAct(target_x_range)) {
1129
- //2.该点在其中,计算point和item上边框的垂直距离
1130
- distance = Math.pow(y_pos - point.y, 2);
1131
- } else if (point.x > x_pos + item.width - 1) {
1132
- //3.该点在其后,计算point和item左上角的距离
1133
- distance =
1134
- Math.pow(point.x - (x_pos + item.width - 1), 2) +
1135
- Math.pow(y_pos - point.y, 2);
1136
- }
1137
- // point与item上边框的距离作为权值
1138
- direction_weighted = Math.abs(point.y - y_pos);
1139
- break;
1140
- default:
1141
- console.log("direction is error:" + direction);
1142
- break;
1143
- }
1144
- if (min_distance < 0) {
1145
- // 设置首个找到的项目
1146
- min_distance = distance;
1147
- min_direction_weighted = direction_weighted;
1148
- min_distance_item = item;
1149
- } else {
1150
- if (
1151
- min_direction_weighted > direction_weighted ||
1152
- (min_direction_weighted === direction_weighted &&
1153
- min_distance > distance)
1154
- ) {
1155
- // 先进行权值比较,在权值相等时,再比较距离
1156
- min_distance = distance;
1157
- min_direction_weighted = direction_weighted;
1158
- min_distance_item = item;
1159
- }
1160
- }
913
+ if (min_distance < 0) {
914
+ // 设置首个找到的项目
915
+ min_distance = distance;
916
+ min_direction_weighted = direction_weighted;
917
+ min_distance_item = item;
918
+ } else {
919
+ if (
920
+ min_direction_weighted > direction_weighted ||
921
+ (min_direction_weighted === direction_weighted &&
922
+ min_distance > distance)
923
+ ) {
924
+ // 先进行权值比较,在权值相等时,再比较距离
925
+ min_distance = distance;
926
+ min_direction_weighted = direction_weighted;
927
+ min_distance_item = item;
1161
928
  }
1162
929
  }
930
+ }
931
+ }
1163
932
 
1164
- if (min_distance_item) {
1165
- return min_distance_item.id;
1166
- } else {
1167
- return 0;
1168
- }
1169
- },
933
+ if (min_distance_item) {
934
+ return min_distance_item.id;
935
+ } else {
936
+ return 0;
937
+ }
938
+ };
1170
939
 
1171
- _onClick(index) {
1172
- return this.innerData[index].itemHandler.onClick?.();
1173
- },
940
+ const onKeyDown = (ev) => {
941
+ if (innerData.length == 0) {
942
+ const edgeDirectionMap = {
943
+ 37: EdgeDirection.left,
944
+ 38: EdgeDirection.top,
945
+ 39: EdgeDirection.right,
946
+ 40: EdgeDirection.bottom,
947
+ };
948
+ if (typeof edgeDirectionMap[ev.keyCode] !== "undefined") {
949
+ props.onEdge?.({
950
+ direction: edgeDirectionMap[ev.keyCode],
951
+ rect: {
952
+ x: 0,
953
+ y: 0,
954
+ width: 0,
955
+ height: 0,
956
+ },
957
+ });
958
+ return true;
959
+ }
960
+ return false;
961
+ }
962
+ let horizontal_direction = 0;
963
+ let vertical_direction = 0;
964
+ switch (ev.keyCode) {
965
+ case 37:
966
+ horizontal_direction = -1;
967
+ _moveToNext(horizontal_direction, vertical_direction);
968
+ break;
969
+ case 38:
970
+ vertical_direction = -1;
971
+ _moveToNext(horizontal_direction, vertical_direction);
972
+ break;
973
+ case 39:
974
+ horizontal_direction = 1;
975
+ _moveToNext(horizontal_direction, vertical_direction);
976
+ break;
977
+ case 40:
978
+ vertical_direction = 1;
979
+ _moveToNext(horizontal_direction, vertical_direction);
980
+ break;
981
+ case 13:
982
+ onItemClick(templateParser.FocusIdToIndex(focusId));
983
+ break;
984
+ default:
985
+ //只接受上下左右确定键
986
+ return false;
987
+ }
988
+ return true;
989
+ };
1174
990
 
1175
- onKeyDown(ev) {
1176
- if (this.innerData.length == 0) {
1177
- const edgeDirectionMap = {
1178
- 37: EdgeDirection.left,
1179
- 38: EdgeDirection.top,
1180
- 39: EdgeDirection.right,
1181
- 40: EdgeDirection.bottom,
1182
- };
1183
- if (typeof edgeDirectionMap[ev.keyCode] !== "undefined") {
1184
- this.onEdge?.({
1185
- direction: edgeDirectionMap[ev.keyCode],
1186
- rect: {
1187
- x: 0,
1188
- y: 0,
1189
- width: 0,
1190
- height: 0,
1191
- },
991
+ const _slideTo = (target, animObj) => {
992
+ if (props.direction === HORIZONTAL) {
993
+ _updatePosition(-target, 0, animObj);
994
+ } else {
995
+ _updatePosition(0, -target, animObj);
996
+ }
997
+ };
998
+
999
+ const _onTemplateAdd = (item) => {
1000
+ let obj = {
1001
+ data: item,
1002
+ index: innerData.length,
1003
+ controller: reactive({
1004
+ zIndex: 0,
1005
+ }),
1006
+ mounted: false,
1007
+ itemDivRef: null,
1008
+ touchInited: false,
1009
+ refCallback(el) {
1010
+ if (el == null) {
1011
+ this.touchInited = false;
1012
+ this.customerCallback = {};
1013
+ }
1014
+ this.itemDivRef = el;
1015
+ },
1016
+ slotMounted: ref(false),
1017
+ slotDivRef(el) {
1018
+ if (!this.slotMounted.value && el) {
1019
+ this.slotMounted.value = true;
1020
+ if (callFocusAfterUpdate && this.data.id === focusId) {
1021
+ nextTick(() => {
1022
+ onItemFocus(templateParser.FocusIdToIndex(focusId), preEdgeRect);
1192
1023
  });
1193
- return true;
1024
+ callFocusAfterUpdate = false;
1194
1025
  }
1195
- return false;
1026
+ } else if (!el && this.slotMounted.value) {
1027
+ this.slotMounted.value = false;
1196
1028
  }
1197
- let horizontal_direction = 0;
1198
- let vertical_direction = 0;
1199
- switch (ev.keyCode) {
1200
- case 37:
1201
- horizontal_direction = -1;
1202
- this._moveToNext(horizontal_direction, vertical_direction);
1203
- break;
1204
- case 38:
1205
- vertical_direction = -1;
1206
- this._moveToNext(horizontal_direction, vertical_direction);
1207
- break;
1208
- case 39:
1209
- horizontal_direction = 1;
1210
- this._moveToNext(horizontal_direction, vertical_direction);
1211
- break;
1212
- case 40:
1213
- vertical_direction = 1;
1214
- this._moveToNext(horizontal_direction, vertical_direction);
1215
- break;
1216
- case 13:
1217
- this._onClick(this.templateParser.FocusIdToIndex(this.focusId));
1218
- break;
1219
- default:
1220
- //只接受上下左右确定键
1221
- return false;
1222
- }
1223
- return true;
1224
1029
  },
1225
-
1226
- _slideTo(target, animObj) {
1227
- if (this.direction === HORIZONTAL) {
1228
- this.rootElement.updatePosition(-target, 0, animObj);
1229
- } else {
1230
- this.rootElement.updatePosition(0, -target, animObj);
1231
- }
1030
+ customerCallback: {},
1031
+ register: {
1032
+ register(name, func) {
1033
+ this.customerCallback[name] = func;
1034
+ },
1035
+ unregister(name) {
1036
+ delete this.customerCallback[name];
1037
+ },
1038
+ },
1039
+ callbacks: {
1040
+ callable(name) {
1041
+ return this.slotMounted.value && this.customerCallback[name];
1042
+ },
1043
+ onFocus(preEdge) {
1044
+ this.customerCallback.onFocus?.(preEdge);
1045
+ },
1046
+ onBlur() {
1047
+ this.customerCallback.onBlur?.();
1048
+ },
1049
+ onClick() {
1050
+ this.customerCallback.onClick?.();
1051
+ },
1052
+ onWidgetEdge(rect) {
1053
+ this.customerCallback.onWidgetEdge?.(rect);
1054
+ },
1232
1055
  },
1056
+ itemConfig: props.itemConfig?.(item.data),
1057
+ query: {
1058
+ id: item.id,
1059
+ index: item.index,
1060
+ position: _getPosition,
1061
+ templatePosition: _getTemplatePosition,
1062
+ absolutePosition: _getAbsolutePosition,
1063
+ getCurrentFocusId: _getCurrentId,
1064
+ slideTo: slideTo,
1065
+ },
1066
+ };
1067
+ bindFunctions(obj, obj);
1068
+ innerData.push(obj);
1069
+ if (item.permanent) {
1070
+ permanentItemList.push({
1071
+ index: innerData.length - 1,
1072
+ alreadyShow: false,
1073
+ });
1074
+ }
1075
+ const lastItem = templateParser.GetItem(-1);
1076
+ if (props.direction == VERTICAL) {
1077
+ touchContainerH.value = lastItem.yPos + lastItem.height - 1;
1078
+ } else {
1079
+ touchContainerW.value = lastItem.xPos + lastItem.width - 1;
1080
+ }
1081
+ };
1233
1082
 
1234
- _onTemplateAdd(item) {
1235
- this.innerData.push({
1236
- data: item,
1237
- index: this.innerData.length,
1238
- controller: reactive({
1239
- // visible: false,
1240
- zIndex: 0,
1241
- }),
1242
- mounted: false,
1243
- itemRef: null,
1244
- itemHandler: {},
1245
- itemConfig: this.itemConfig?.(item.data),
1246
- });
1247
- if (item.permanent) {
1248
- this.permanentItemList.push({
1249
- index: this.innerData.length - 1,
1250
- alreadyShow: false,
1251
- });
1083
+ const _itemOnFocusSideEffect = (item, edgeRect) => {
1084
+ _onFocusChange(item.data.id);
1085
+ if (item.itemDivRef) {
1086
+ let event = {
1087
+ type: "focusRect",
1088
+ direction: edgeRect?.direction?.description,
1089
+ element: toRaw(item.itemDivRef),
1090
+ };
1091
+ _bubbleCustomerEvent(event);
1092
+ }
1093
+ };
1094
+
1095
+ const _onCustomerEvent = (ev) => {
1096
+ if (ev.type === "focusRect") {
1097
+ if (ev.ownerNode == exportObject) {
1098
+ return false;
1099
+ }
1100
+ let item_div = ev.element;
1101
+ let direction = 0;
1102
+ if (props.direction == HORIZONTAL) {
1103
+ if (ev.direction == "left") {
1104
+ direction = -1;
1105
+ } else if (ev.direction == "right") {
1106
+ direction = 1;
1252
1107
  }
1253
- const lastItem = this.templateParser.GetItem(-1);
1254
- if (this.direction == VERTICAL) {
1255
- this.touchContainerH = lastItem.yPos + lastItem.height - 1;
1256
- } else {
1257
- this.touchContainerW = lastItem.xPos + lastItem.width - 1;
1108
+ } else {
1109
+ if (ev.direction == "top") {
1110
+ direction = -1;
1111
+ } else if (ev.direction == "bottom") {
1112
+ direction = 1;
1258
1113
  }
1259
- },
1114
+ }
1115
+ let item_layout = getPositionRelativeToView(
1116
+ item_div,
1117
+ toRaw(locateDiv.value)
1118
+ );
1260
1119
 
1261
- _onCustomerEvent(ev) {
1262
- if (ev.type === "focusRect") {
1263
- if (ev.ownerNode == this) {
1264
- return false;
1265
- }
1266
- let item_div = ev.element;
1267
- let direction = 0;
1268
- if (this.direction == HORIZONTAL) {
1269
- if (ev.direction == "left") {
1270
- direction = -1;
1271
- } else if (ev.direction == "right") {
1272
- direction = 1;
1273
- }
1274
- } else {
1275
- if (ev.direction == "top") {
1276
- direction = -1;
1277
- } else if (ev.direction == "bottom") {
1278
- direction = 1;
1279
- }
1280
- }
1281
- let item_layout = getPositionRelativeToView(
1282
- item_div,
1283
- this.$refs.rootView.getLocateDiv()
1284
- );
1285
- let obj = {
1286
- xPos: item_layout.left,
1287
- yPos: item_layout.top,
1288
- width: item_layout.width,
1289
- height: item_layout.height,
1290
- index: this.templateParser.FocusIdToIndex(this.focusId),
1291
- };
1292
- let cur_slide = this._calculateVisibleStart(obj, direction);
1293
- if (cur_slide != this.visibleStart) {
1294
- this.visibleStart = cur_slide;
1295
- this.pageUpdater.update(
1296
- this.templateParser,
1297
- this.visibleStart,
1298
- this.visibleStart + this.visibleRangeWithPadding - 1,
1299
- this.focusId,
1300
- true,
1301
- this.permanentItemList
1302
- );
1303
- this.pageUpdater.applyTmp();
1304
- this._slideTo(this.visibleStart, {
1305
- easing: "",
1306
- onstart: null,
1307
- speed: this.slideSetting.Speed,
1308
- onend: this._onSlideEnd,
1309
- });
1120
+ let obj = {
1121
+ xPos: item_layout.left,
1122
+ yPos: item_layout.top,
1123
+ width: item_layout.width,
1124
+ height: item_layout.height,
1125
+ index: templateParser.FocusIdToIndex(focusId),
1126
+ };
1310
1127
 
1311
- return true;
1312
- }
1128
+ let cur_slide = _calculateVisibleStart(obj, direction);
1129
+ if (cur_slide != visibleInfo.start) {
1130
+ visibleInfo.start = cur_slide;
1131
+ pageUpdater.update(
1132
+ templateParser,
1133
+ visibleInfo.startWithPadding - props.keepTraceRange * pageRange,
1134
+ Math.min(
1135
+ visibleInfo.startMax +
1136
+ visibleInfo.range +
1137
+ visibleInfo.padding.end -
1138
+ 1,
1139
+ visibleInfo.endWithPadding + props.keepTraceRange * pageRange
1140
+ ),
1141
+ focusId,
1142
+ true,
1143
+ permanentItemList
1144
+ );
1145
+ pageUpdater.applyTmp();
1146
+ _slideTo(visibleInfo.start, {
1147
+ easing: "",
1148
+ onstart: null,
1149
+ speed: props.slideSetting.Speed,
1150
+ onend: _onSlideEnd,
1151
+ });
1152
+ return true;
1153
+ }
1154
+ }
1155
+ return false;
1156
+ };
1157
+
1158
+ const _bubbleCustomerEvent = (event) => {
1159
+ if (props.sendFocusRectEvent && event) {
1160
+ event.ownerNode = exportObject;
1161
+ toRaw(focusNode.value)?.bubbleCustomerEvent(event);
1162
+ }
1163
+ };
1164
+
1165
+ const _moveToNext = (
1166
+ horizontal_direction,
1167
+ vertical_direction,
1168
+ item_edge_rect
1169
+ ) => {
1170
+ let cur_focus_item = templateParser.GetItemById(focusId);
1171
+ let next_item_id = templateParser.GetNextItem(
1172
+ focusId,
1173
+ vertical_direction,
1174
+ horizontal_direction,
1175
+ props.loopFocus
1176
+ );
1177
+ if (next_item_id >= 0) {
1178
+ preFocusId = focusId;
1179
+ let next_focus_item = templateParser.GetItemById(next_item_id);
1180
+ templateItemAdder.tryAddItem(next_focus_item, 1);
1181
+ focusId = next_focus_item.id;
1182
+
1183
+ let direction =
1184
+ props.direction === VERTICAL ? vertical_direction : horizontal_direction;
1185
+
1186
+ let cur_visible_start = _calculateVisibleStart(next_focus_item, direction);
1187
+ if (
1188
+ !innerData[templateParser.FocusIdToIndex(next_item_id)].itemConfig
1189
+ ?.takeOverSlide &&
1190
+ visibleInfo.start !== cur_visible_start
1191
+ ) {
1192
+ if (next_focus_item.doSlide) {
1193
+ visibleInfo.start = cur_visible_start;
1194
+ let animObj = {
1195
+ easing: "",
1196
+ onstart: null,
1197
+ speed: props.slideSetting.Speed,
1198
+ onend: _onSlideEnd,
1199
+ };
1200
+ _slideTo(visibleInfo.start, animObj);
1313
1201
  }
1314
- return false;
1315
- },
1202
+ pageUpdater.update(
1203
+ templateParser,
1204
+ visibleInfo.startWithPadding - props.keepTraceRange * pageRange,
1205
+ Math.min(
1206
+ visibleInfo.startMax +
1207
+ visibleInfo.range +
1208
+ visibleInfo.padding.end -
1209
+ 1,
1210
+ visibleInfo.endWithPadding + props.keepTraceRange * pageRange
1211
+ ),
1212
+ next_item_id,
1213
+ false,
1214
+ permanentItemList
1215
+ );
1216
+ pageUpdater.applyTmp();
1217
+ }
1316
1218
 
1317
- _bubbleCustomerEvent(event) {
1318
- if (this.sendFocusRectEvent && event) {
1319
- event.ownerNode = this;
1320
- this.$refs.focusNode?.bubbleCustomerEvent(event);
1219
+ let rect;
1220
+ let x_off_set = cur_focus_item.xPos - next_focus_item.xPos;
1221
+ let y_off_set = cur_focus_item.yPos - next_focus_item.yPos;
1222
+ if (item_edge_rect) {
1223
+ item_edge_rect.rect.x += x_off_set;
1224
+ item_edge_rect.rect.y += y_off_set;
1225
+ rect = item_edge_rect;
1226
+ } else {
1227
+ let direction;
1228
+ if (horizontal_direction > 0) {
1229
+ direction = EdgeDirection.right;
1230
+ } else if (horizontal_direction < 0) {
1231
+ direction = EdgeDirection.left;
1232
+ } else if (vertical_direction > 0) {
1233
+ direction = EdgeDirection.bottom;
1234
+ } else if (vertical_direction < 0) {
1235
+ direction = EdgeDirection.top;
1321
1236
  }
1322
- },
1237
+ rect = {
1238
+ direction,
1239
+ rect: {
1240
+ x: x_off_set,
1241
+ y: y_off_set,
1242
+ width: cur_focus_item.width,
1243
+ height: cur_focus_item.height,
1244
+ },
1245
+ };
1246
+ }
1247
+ preEdgeRect = rect;
1248
+ _updateBlurItem();
1249
+ _updateFocusItem();
1250
+ onItemBlur(templateParser.FocusIdToIndex(preFocusId));
1251
+ onItemFocus(templateParser.FocusIdToIndex(focusId), preEdgeRect);
1252
+ } else {
1253
+ let x_off_set = props.direction === VERTICAL ? 0 : visibleInfo.start;
1254
+ let y_off_set = props.direction === VERTICAL ? visibleInfo.start : 0;
1255
+ let edge;
1256
+ if (horizontal_direction === 1) {
1257
+ edge = EdgeDirection.right;
1258
+ }
1259
+ if (horizontal_direction === -1) {
1260
+ edge = EdgeDirection.left;
1261
+ }
1262
+ if (vertical_direction === 1) {
1263
+ edge = EdgeDirection.bottom;
1264
+ }
1265
+ if (vertical_direction === -1) {
1266
+ edge = EdgeDirection.top;
1267
+ }
1268
+ let rect = {
1269
+ x: cur_focus_item.xPos - x_off_set,
1270
+ y: cur_focus_item.yPos - y_off_set,
1271
+ width: cur_focus_item.width,
1272
+ height: cur_focus_item.height,
1273
+ };
1274
+ props.onEdge?.({ direction: edge, rect: rect });
1275
+ innerData[templateParser.FocusIdToIndex(focusId)].callbacks.onWidgetEdge?.({
1276
+ direction: edge,
1277
+ });
1278
+ }
1279
+ };
1323
1280
 
1324
- _moveToNext(horizontal_direction, vertical_direction, item_edge_rect) {
1325
- let cur_focus_item = this.templateParser.GetItemById(this.focusId);
1326
- let next_item_id = this.templateParser.GetNextItem(
1327
- this.focusId,
1328
- vertical_direction,
1329
- horizontal_direction,
1330
- this.loopFocus
1281
+ const _calculateVisibleStart = (target_item, direction) => {
1282
+ if (!target_item) {
1283
+ console.error("MetroWidget: _calculateVisibleStart target item is null");
1284
+ return 0;
1285
+ }
1286
+ preAnchorItemIndex = target_item.index;
1287
+ let pos_key = directionFreeKeyMap.pos[vertical];
1288
+ let size_key = directionFreeKeyMap.size[vertical];
1289
+ let center_key = directionFreeKeyMap.center[vertical];
1290
+ let new_visible_start = visibleInfo.start;
1291
+
1292
+ switch (props.slideSetting.Type) {
1293
+ case SlideSetting.Type.FIX_POSITION:
1294
+ //FIX_POSITION 模式会将当前 item 的中心固定到指定位置
1295
+ new_visible_start = Math.ceil(
1296
+ target_item[center_key] -
1297
+ visibleInfo.range * props.slideSetting.FixPercent
1331
1298
  );
1332
- if (next_item_id >= 0) {
1333
- this.preFocusId = this.focusId;
1334
- let next_focus_item = this.templateParser.GetItemById(next_item_id);
1335
- this.templateItemAdder.tryAddItem(next_focus_item, 1);
1336
- this.focusId = next_focus_item.id;
1337
-
1338
- let direction =
1339
- this.direction === VERTICAL
1340
- ? vertical_direction
1341
- : horizontal_direction;
1342
-
1343
- let cur_visible_start = this._calculateVisibleStart(
1344
- next_focus_item,
1345
- direction
1346
- );
1299
+ break;
1300
+ case SlideSetting.Type.WHOLE_PAGE:
1301
+ new_visible_start = templateParser.GetItem(target_item.pageHeadIndex)[
1302
+ pos_key
1303
+ ];
1304
+ break;
1305
+ case SlideSetting.Type.SEAMLESS:
1306
+ if (direction > 0) {
1347
1307
  if (
1348
- !this.innerData[this.templateParser.FocusIdToIndex(next_item_id)]
1349
- .itemConfig?.takeOverSlide &&
1350
- this.visibleStart !== cur_visible_start
1308
+ target_item[pos_key] + target_item[size_key] >
1309
+ visibleInfo.start + visibleInfo.range * props.slideSetting.EndPercent
1351
1310
  ) {
1352
- if (next_focus_item.doSlide) {
1353
- this.visibleStart = cur_visible_start;
1354
- let animObj = {
1355
- easing: "",
1356
- onstart: null,
1357
- speed: this.slideSetting.Speed,
1358
- onend: this._onSlideEnd,
1359
- };
1360
- this._slideTo(this.visibleStart, animObj);
1361
- }
1362
- this.pageUpdater.update(
1363
- this.templateParser,
1364
- cur_visible_start,
1365
- cur_visible_start + this.visibleRangeWithPadding - 1,
1366
- next_item_id,
1367
- false,
1368
- this.permanentItemList
1369
- );
1370
- this.pageUpdater.applyTmp();
1371
- }
1372
-
1373
- let rect;
1374
- let x_off_set = cur_focus_item.xPos - next_focus_item.xPos;
1375
- let y_off_set = cur_focus_item.yPos - next_focus_item.yPos;
1376
- if (item_edge_rect) {
1377
- item_edge_rect.rect.x += x_off_set;
1378
- item_edge_rect.rect.y += y_off_set;
1379
- rect = item_edge_rect;
1380
- } else {
1381
- let direction;
1382
- if (horizontal_direction > 0) {
1383
- direction = EdgeDirection.right;
1384
- } else if (horizontal_direction < 0) {
1385
- direction = EdgeDirection.left;
1386
- } else if (vertical_direction > 0) {
1387
- direction = EdgeDirection.bottom;
1388
- } else if (vertical_direction < 0) {
1389
- direction = EdgeDirection.top;
1390
- }
1391
- rect = {
1392
- direction,
1393
- rect: {
1394
- x: x_off_set,
1395
- y: y_off_set,
1396
- width: cur_focus_item.width,
1397
- height: cur_focus_item.height,
1398
- },
1399
- };
1400
- }
1401
- this.preEdgeRect = rect;
1402
- this._updateBlurItem();
1403
- this._updateFocusItem();
1404
- if (this.isFocus) {
1405
- this.innerData[
1406
- this.templateParser.FocusIdToIndex(this.preFocusId)
1407
- ].itemHandler.onBlur?.();
1311
+ new_visible_start =
1312
+ target_item[pos_key] +
1313
+ target_item[size_key] -
1314
+ visibleInfo.range * props.slideSetting.EndPercent;
1408
1315
  }
1316
+ } else if (direction < 0) {
1409
1317
  if (
1410
- this.isFocus &&
1411
- this.innerData[this.templateParser.FocusIdToIndex(this.focusId)]
1412
- .mounted
1318
+ target_item[pos_key] <
1319
+ visibleInfo.start +
1320
+ visibleInfo.range * props.slideSetting.StartPercent
1413
1321
  ) {
1414
- this.innerData[
1415
- this.templateParser.FocusIdToIndex(this.focusId)
1416
- ].itemHandler.onFocus?.(this.preEdgeRect);
1322
+ new_visible_start =
1323
+ target_item[pos_key] -
1324
+ visibleInfo.range * props.slideSetting.StartPercent;
1417
1325
  }
1418
1326
  } else {
1419
- let x_off_set = this.direction === VERTICAL ? 0 : this.visibleStart;
1420
- let y_off_set = this.direction === VERTICAL ? this.visibleStart : 0;
1421
- let edge;
1422
- if (horizontal_direction === 1) {
1423
- edge = EdgeDirection.right;
1424
- }
1425
- if (horizontal_direction === -1) {
1426
- edge = EdgeDirection.left;
1427
- }
1428
- if (vertical_direction === 1) {
1429
- edge = EdgeDirection.bottom;
1430
- }
1431
- if (vertical_direction === -1) {
1432
- edge = EdgeDirection.top;
1433
- }
1434
- let rect = {
1435
- x: cur_focus_item.xPos - x_off_set,
1436
- y: cur_focus_item.yPos - y_off_set,
1437
- width: cur_focus_item.width,
1438
- height: cur_focus_item.height,
1439
- };
1440
- if (this.onEdge) {
1441
- this.onEdge({ direction: edge, rect: rect });
1327
+ //不是沿widget方向的移动
1328
+ if (target_item[pos_key] < visibleInfo.start) {
1329
+ new_visible_start =
1330
+ target_item[pos_key] -
1331
+ visibleInfo.range * props.slideSetting.StartPercent;
1332
+ } else if (
1333
+ target_item[pos_key] + target_item[size_key] >
1334
+ visibleInfo.end
1335
+ ) {
1336
+ new_visible_start =
1337
+ target_item[pos_key] +
1338
+ target_item[size_key] -
1339
+ visibleInfo.range * props.slideSetting.EndPercent;
1442
1340
  }
1443
- this.innerData[
1444
- this.templateParser.FocusIdToIndex(this.focusId)
1445
- ].itemHandler.reachEdge?.({
1446
- direction: edge,
1447
- });
1448
1341
  }
1449
- },
1342
+ break;
1343
+ default:
1344
+ console.error(
1345
+ "MetroWidget: undefined slide type",
1346
+ props.slideSetting.Type
1347
+ );
1348
+ }
1450
1349
 
1451
- _adjustToValidPosition(visible_start, adjust_end) {
1452
- //TODO 优化
1453
- let last_item = this.templateParser.GetItem(-1);
1454
- let pos_key = directionFreeKeyMap.pos[this.direction === VERTICAL];
1455
- let size_key = directionFreeKeyMap.size[this.direction === VERTICAL];
1456
- let padding = _getPadding(this.padding);
1457
-
1458
- let padding_offset =
1459
- this.direction === VERTICAL
1460
- ? padding["bottom"] + padding["top"]
1461
- : padding["right"] + padding["left"];
1462
- let visible_range =
1463
- (this.direction === VERTICAL ? this.height : this.width) -
1464
- padding_offset;
1465
-
1466
- let last_position = last_item[pos_key] + last_item[size_key];
1467
- let last_item_off_set = last_position - visible_range;
1468
- last_item_off_set = last_item_off_set < 0 ? 0 : last_item_off_set;
1469
- if (adjust_end && visible_start > last_item_off_set) {
1470
- return last_item_off_set;
1471
- } else if (visible_start < 0) {
1472
- return 0;
1473
- } else {
1474
- return visible_start;
1475
- }
1476
- },
1350
+ if ((props.slideSetting.BoundaryProtect & SlideSetting.START_PROTECT) > 0) {
1351
+ let boundary = 0;
1352
+ if (!templateParser.GetItem(0).focusable) {
1353
+ //首个元素是占位符
1354
+ boundary = templateParser.GetItem(0)[size_key];
1355
+ }
1356
+ new_visible_start = new_visible_start < boundary ? 0 : new_visible_start;
1357
+ }
1358
+ if ((props.slideSetting.BoundaryProtect & SlideSetting.END_PROTECT) > 0) {
1359
+ let last_item = templateParser.GetItem(-1);
1360
+ let last_visible_start =
1361
+ last_item[pos_key] + last_item[size_key] - visibleInfo.range;
1362
+ last_visible_start = last_visible_start < 0 ? 0 : last_visible_start;
1363
+ let boundary = last_visible_start;
1364
+ if (!last_item.focusable) {
1365
+ //最后个元素是占位符
1366
+ boundary = last_item[pos_key] - visibleInfo.range;
1367
+ }
1368
+ new_visible_start =
1369
+ new_visible_start > boundary ? last_visible_start : new_visible_start;
1370
+ }
1371
+ return new_visible_start;
1372
+ };
1477
1373
 
1478
- _calculateVisibleStart(target_item, direction) {
1479
- if (!target_item) {
1480
- console.error(
1481
- "MetroWidget: _calculateVisibleStart target item is null"
1482
- );
1483
- return 0;
1484
- }
1485
- this.preAnchorItemIndex = target_item.index;
1486
- let pos_key = directionFreeKeyMap.pos[this.vertical];
1487
- let size_key = directionFreeKeyMap.size[this.vertical];
1488
- let center_key = directionFreeKeyMap.center[this.vertical];
1489
- let new_visible_start = this.visibleStart;
1490
-
1491
- switch (this.slideSetting.Type) {
1492
- case SlideSetting.Type.FIX_POSITION:
1493
- //FIX_POSITION 模式会将当前 item 的中心固定到指定位置
1494
- new_visible_start = Math.ceil(
1495
- target_item[center_key] -
1496
- this.visibleRange * this.slideSetting.FixPercent
1497
- );
1498
- break;
1499
- case SlideSetting.Type.WHOLE_PAGE:
1500
- new_visible_start = this.templateParser.GetItem(
1501
- target_item.pageHeadIndex
1502
- )[pos_key];
1503
- break;
1504
- case SlideSetting.Type.SEAMLESS:
1505
- if (direction > 0) {
1506
- if (
1507
- target_item[pos_key] + target_item[size_key] >
1508
- this.visibleStart +
1509
- this.visibleRange * this.slideSetting.EndPercent
1510
- ) {
1511
- new_visible_start =
1512
- target_item[pos_key] +
1513
- target_item[size_key] -
1514
- this.visibleRange * this.slideSetting.EndPercent;
1515
- }
1516
- } else if (direction < 0) {
1517
- if (
1518
- target_item[pos_key] <
1519
- this.visibleStart +
1520
- this.visibleRange * this.slideSetting.StartPercent
1521
- ) {
1522
- new_visible_start =
1523
- target_item[pos_key] -
1524
- this.visibleRange * this.slideSetting.StartPercent;
1525
- }
1526
- } else {
1527
- //不是沿widget方向的移动
1528
- if (target_item[pos_key] < this.visibleStart) {
1529
- new_visible_start =
1530
- target_item[pos_key] -
1531
- this.visibleRange * this.slideSetting.StartPercent;
1532
- } else if (
1533
- target_item[pos_key] + target_item[size_key] >
1534
- this.visibleStart + this.visibleRange
1535
- ) {
1536
- new_visible_start =
1537
- target_item[pos_key] +
1538
- target_item[size_key] -
1539
- this.visibleRange * this.slideSetting.EndPercent;
1540
- }
1541
- }
1542
- break;
1543
- default:
1544
- console.error(
1545
- "MetroWidget: undefined slide type",
1546
- this.slideSetting.Type
1547
- );
1548
- }
1374
+ const _onFocusableItemEdge = (edge_info) => {
1375
+ let horizontal_direction = 0;
1376
+ let vertical_direction = 0;
1377
+ switch (edge_info.direction) {
1378
+ case EdgeDirection.left:
1379
+ horizontal_direction = -1;
1380
+ break;
1381
+ case EdgeDirection.right:
1382
+ horizontal_direction = 1;
1383
+ break;
1384
+ case EdgeDirection.top:
1385
+ vertical_direction = -1;
1386
+ break;
1387
+ case EdgeDirection.bottom:
1388
+ vertical_direction = 1;
1389
+ break;
1390
+ default:
1391
+ break;
1392
+ }
1393
+ _moveToNext(horizontal_direction, vertical_direction, edge_info);
1394
+ };
1549
1395
 
1550
- if (
1551
- (this.slideSetting.BoundaryProtect & SlideSetting.START_PROTECT) >
1552
- 0
1553
- ) {
1554
- let boundary = 0;
1555
- if (!this.templateParser.GetItem(0).focusable) {
1556
- //首个元素是占位符
1557
- boundary = this.templateParser.GetItem(0)[size_key];
1558
- }
1559
- new_visible_start =
1560
- new_visible_start < boundary ? 0 : new_visible_start;
1561
- }
1562
- if ((this.slideSetting.BoundaryProtect & SlideSetting.END_PROTECT) > 0) {
1563
- let last_item = this.templateParser.GetItem(-1);
1564
- let last_visible_start =
1565
- last_item[pos_key] + last_item[size_key] - this.visibleRange;
1566
- last_visible_start = last_visible_start < 0 ? 0 : last_visible_start;
1567
- let boundary = last_visible_start;
1568
- if (!last_item.focusable) {
1569
- //最后个元素是占位符
1570
- boundary = last_item[pos_key] - this.visibleRange;
1571
- }
1572
- new_visible_start =
1573
- new_visible_start > boundary ? last_visible_start : new_visible_start;
1574
- }
1575
- return new_visible_start;
1576
- },
1396
+ const _ifValidEnterRect = (rect_info) => {
1397
+ return rect_info && rect_info.direction && rect_info.rect;
1398
+ };
1577
1399
 
1578
- _onFocusableItemEdge(edge_info) {
1579
- let horizontal_direction = 0;
1580
- let vertical_direction = 0;
1581
- switch (edge_info.direction) {
1582
- case EdgeDirection.left:
1583
- horizontal_direction = -1;
1584
- break;
1585
- case EdgeDirection.right:
1586
- horizontal_direction = 1;
1587
- break;
1588
- case EdgeDirection.top:
1589
- vertical_direction = -1;
1590
- break;
1591
- case EdgeDirection.bottom:
1592
- vertical_direction = 1;
1593
- break;
1594
- default:
1595
- break;
1596
- }
1597
- this._moveToNext(horizontal_direction, vertical_direction, edge_info);
1598
- },
1400
+ const _setZIndex = (index, z_index) => {
1401
+ if (innerData[index]) {
1402
+ innerData[index].controller.zIndex = z_index;
1403
+ }
1404
+ };
1599
1405
 
1600
- _ifValidEnterRect(rect_info) {
1601
- return rect_info && rect_info.direction && rect_info.rect;
1602
- },
1406
+ const _onFocus = (params) => {
1407
+ isFocus = true;
1408
+ preFocusId = -1;
1409
+ if (innerData.length === 0) {
1410
+ console.warn(`MetroWidget: ${props.name} get focus while data is empty.`);
1411
+ return;
1412
+ }
1413
+ let focus_id =
1414
+ typeof enterFocusId !== "undefined" &&
1415
+ enterFocusId >= 0 &&
1416
+ enterFocusId < templateParser.GetTemplate().List.length
1417
+ ? enterFocusId
1418
+ : focusId;
1419
+ focus_id = _ifValidEnterRect(enterFocusRect)
1420
+ ? _calculateNearestItemByRect(pageUpdater.getRange(), enterFocusRect)
1421
+ : focus_id;
1422
+ preEdgeRect = enterFocusRect;
1423
+ focusId = focus_id;
1424
+ enterFocusId = -1;
1425
+ enterFocusRect = null;
1426
+ _updateFocusItem();
1427
+ onItemFocus(templateParser.FocusIdToIndex(focusId), preEdgeRect);
1428
+ props.onFocus?.();
1429
+ };
1603
1430
 
1604
- _setZIndex(index, z_index) {
1605
- if (this.innerData[index]) {
1606
- this.innerData[index].controller.zIndex = z_index;
1607
- }
1608
- },
1431
+ const _onBlur = () => {
1432
+ isFocus = false;
1433
+ enterFocusId = -1;
1434
+ enterFocusRect = null;
1435
+ preEdgeRect = null;
1436
+ if (innerData.length === 0) {
1437
+ return;
1438
+ }
1439
+ preFocusId = focusId;
1440
+ _updateBlurItem();
1441
+ innerData[templateParser.FocusIdToIndex(preFocusId)].callbacks.onBlur();
1609
1442
 
1610
- _onFocus() {
1611
- this.isFocus = true;
1612
- this.preFocusId = -1;
1613
- if (this.innerData.length === 0) {
1614
- console.warn(
1615
- `MetroWidget: ${this.name} get focus while data is empty.`
1616
- );
1617
- return;
1618
- }
1619
- let focus_id =
1620
- typeof this.enterFocusId !== "undefined" &&
1621
- this.enterFocusId >= 0 &&
1622
- this.enterFocusId < this.templateParser.GetTemplate().List.length
1623
- ? this.enterFocusId
1624
- : this.focusId;
1625
- focus_id = this._ifValidEnterRect(this.enterFocusRect)
1626
- ? this._calculateNearestItemByRect(
1627
- this.pageUpdater.getRange(),
1628
- this.enterFocusRect
1629
- )
1630
- : focus_id;
1631
- this.preEdgeRect = this.enterFocusRect;
1632
- this.focusId = focus_id;
1633
- this.enterFocusId = -1;
1634
- this.enterFocusRect = null;
1635
- this._updateFocusItem();
1636
- if (
1637
- this.isFocus &&
1638
- this.innerData[this.templateParser.FocusIdToIndex(this.focusId)].mounted
1639
- ) {
1640
- this.innerData[
1641
- this.templateParser.FocusIdToIndex(this.focusId)
1642
- ].itemHandler.onFocus?.(this.preEdgeRect);
1643
- }
1443
+ props.onBlur?.();
1444
+ };
1644
1445
 
1645
- if (this.onFocus) {
1646
- this.onFocus();
1647
- }
1648
- },
1446
+ const _onSlideEnd = (event) => {
1447
+ if (event && event.stopPropagation) {
1448
+ event.stopPropagation();
1449
+ }
1450
+ pageUpdater.apply();
1451
+ };
1649
1452
 
1650
- _onBlur() {
1651
- this.isFocus = false;
1652
- this.enterFocusId = -1;
1653
- this.enterFocusRect = null;
1654
- this.preEdgeRect = null;
1655
- if (this.innerData.length === 0) {
1656
- return;
1657
- }
1658
- this.preFocusId = this.focusId;
1659
- this._updateBlurItem();
1660
- this.innerData[
1661
- this.templateParser.FocusIdToIndex(this.preFocusId)
1662
- ].itemHandler.onBlur?.();
1663
-
1664
- if (this.onBlur) {
1665
- this.onBlur();
1666
- }
1667
- },
1453
+ const _updateFocusItem = () => {
1454
+ _setZIndex(templateParser.FocusIdToIndex(focusId), innerData.length);
1455
+ };
1668
1456
 
1669
- _onSlideEnd(event) {
1670
- if (event && event.stopPropagation) {
1671
- event.stopPropagation();
1672
- }
1673
- this.pageUpdater.apply();
1674
- },
1457
+ const _updateBlurItem = () => {
1458
+ _setZIndex(templateParser.FocusIdToIndex(preFocusId), 0);
1459
+ };
1675
1460
 
1676
- _onContentUpdate() {
1677
- this._updateFocusItem();
1678
- },
1461
+ const _updateFocusByDragInfo = (viewX, viewY) => {
1462
+ let enterFocusRect = null;
1463
+ //模拟最小区域作为输入区域
1464
+ if (props.direction === VERTICAL) {
1465
+ enterFocusRect = {
1466
+ direction: EdgeDirection.top,
1467
+ rect: {
1468
+ x: props.left - viewX,
1469
+ y: props.top - viewY,
1470
+ width: 10,
1471
+ height: 10,
1472
+ },
1473
+ };
1474
+ } else {
1475
+ enterFocusRect = {
1476
+ direction: EdgeDirection.left,
1477
+ rect: {
1478
+ x: props.left - viewX,
1479
+ y: props.top - viewY,
1480
+ width: 10,
1481
+ height: 10,
1482
+ },
1483
+ };
1484
+ }
1485
+ focusId = _calculateNearestItemByRect(pageUpdater.getRange(), enterFocusRect);
1486
+ };
1679
1487
 
1680
- _updateFocusItem() {
1681
- this._setZIndex(
1682
- this.templateParser.FocusIdToIndex(this.focusId),
1683
- this.innerData.length
1684
- );
1685
- },
1488
+ const _onDragUpdateItem = (visible_start, visible_end) => {
1489
+ templateItemAdder.tryAddItemByPosition(visible_end);
1490
+ pageUpdater.update(
1491
+ templateParser,
1492
+ visible_start,
1493
+ visible_end,
1494
+ 0,
1495
+ false,
1496
+ permanentItemList
1497
+ );
1498
+ pageUpdater.apply();
1686
1499
 
1687
- _updateBlurItem() {
1688
- this._setZIndex(this.templateParser.FocusIdToIndex(this.preFocusId), 0);
1689
- },
1500
+ Forge.sRenderBridge.InstantPerformSwap();
1501
+ };
1690
1502
 
1691
- _updateFocusByDragInfo(viewX, viewY) {
1692
- let enterFocusRect = null;
1693
- //模拟最小区域作为输入区域
1694
- if (this.direction === VERTICAL) {
1695
- enterFocusRect = {
1696
- direction: EdgeDirection.top,
1697
- rect: {
1698
- x: this.left - viewX,
1699
- y: this.top - viewY,
1700
- width: 10,
1701
- height: 10,
1702
- },
1703
- };
1704
- } else {
1705
- enterFocusRect = {
1706
- direction: EdgeDirection.left,
1707
- rect: {
1708
- x: this.left - viewX,
1709
- y: this.top - viewY,
1710
- width: 10,
1711
- height: 10,
1712
- },
1713
- };
1503
+ const _getTouchListener = () => {
1504
+ if (!props.enableTouch) {
1505
+ return null;
1506
+ }
1507
+ let callback = {
1508
+ OnDragStart: (msg) => {
1509
+ if (mounted) {
1510
+ Promise.resolve().then(() => {
1511
+ let cur_visible_start = visibleInfo.start - pageRange * 2;
1512
+ let cur_visible_end = visibleInfo.start + pageRange * 3 - 1;
1513
+ preUpdateVisibleStart = cur_visible_start;
1514
+ _onDragUpdateItem(cur_visible_start, cur_visible_end);
1515
+ });
1714
1516
  }
1715
- this.focusId = this._calculateNearestItemByRect(
1716
- this.pageUpdater.getRange(),
1717
- enterFocusRect
1718
- );
1719
- },
1720
-
1721
- _registerRootView(ele) {
1722
- this.rootElement = ele;
1723
- },
1724
-
1725
- _onDragUpdateItem(visible_start, visible_end) {
1726
- this.templateItemAdder.tryAddItemByPosition(visible_end);
1727
- let baseItemId = this.visibleRangeSearchBaseItem
1728
- ? this.visibleRangeSearchBaseItem
1729
- : 0;
1730
- this.pageUpdater.update(
1731
- this.templateParser,
1732
- visible_start,
1733
- visible_end,
1734
- baseItemId,
1735
- false,
1736
- this.permanentItemList
1737
- );
1738
- this.pageUpdater.apply();
1739
-
1740
- Forge.sRenderBridge.InstantPerformSwap();
1517
+ return true;
1741
1518
  },
1742
-
1743
- _getTouchListener() {
1744
- if (!this.enableTouch) {
1745
- return null;
1746
- }
1747
- let callback = {
1748
- OnDragStart: (msg) => {
1749
- //删除焦点
1750
- if (this.mounted) {
1751
- Promise.resolve().then(() => {
1752
- let cur_visible_start =
1753
- this.visibleStart - this.visibleRangeWithPadding * 2;
1754
- let cur_visible_end =
1755
- this.visibleStart + this.visibleRangeWithPadding * 3 - 1;
1756
- this.preUpdateVisibleStart = cur_visible_start;
1757
- this._onDragUpdateItem(cur_visible_start, cur_visible_end);
1758
- });
1519
+ OnMoved: (msg) => {
1520
+ if (mounted) {
1521
+ Promise.resolve().then(() => {
1522
+ if (
1523
+ typeof msg.viewY != "undefined" &&
1524
+ typeof msg.viewX != "undefined"
1525
+ ) {
1526
+ if (props.direction === VERTICAL) {
1527
+ visibleInfo.start = -msg.viewY;
1528
+ } else {
1529
+ visibleInfo.start = -msg.viewX;
1530
+ }
1531
+ if (visibleInfo.start < 0) {
1532
+ visibleInfo.start = 0;
1533
+ }
1759
1534
  }
1760
- return true;
1761
- },
1762
- OnMoved: (msg) => {
1763
- if (this.mounted) {
1764
- Promise.resolve().then(() => {
1765
- if (
1766
- typeof msg.viewY != "undefined" &&
1767
- typeof msg.viewX != "undefined"
1768
- ) {
1769
- if (this.direction === VERTICAL) {
1770
- this.visibleStart = -msg.viewY;
1771
- } else {
1772
- this.visibleStart = -msg.viewX;
1773
- }
1774
- if (this.visibleStart < 0) {
1775
- this.visibleStart = 0;
1776
- }
1777
- }
1778
- if (
1779
- Math.abs(this.visibleStart - this.preUpdateVisibleStart) <=
1780
- this.visibleRangeWithPadding
1781
- ) {
1782
- let cur_visible_start =
1783
- this.visibleStart - this.visibleRangeWithPadding * 2;
1784
- let cur_visible_end =
1785
- this.visibleStart + this.visibleRangeWithPadding * 3 - 1;
1786
- this.preUpdateVisibleStart = cur_visible_start;
1787
- this._onDragUpdateItem(cur_visible_start, cur_visible_end);
1788
- }
1789
- });
1535
+ if (
1536
+ Math.abs(visibleInfo.start - preUpdateVisibleStart) <= pageRange
1537
+ ) {
1538
+ let cur_visible_start = visibleInfo.start - pageRange * 2;
1539
+ let cur_visible_end = visibleInfo.start + pageRange * 3 - 1;
1540
+ preUpdateVisibleStart = cur_visible_start;
1541
+ _onDragUpdateItem(cur_visible_start, cur_visible_end);
1790
1542
  }
1543
+ });
1544
+ }
1791
1545
 
1792
- return true;
1793
- },
1794
- OnDragEnd: (msg) => {
1795
- this.$refs.rootView?.updatePosition(msg["viewX"], msg["viewY"], null);
1796
- this.preUpdateVisibleStart = this.visibleStart;
1797
- this._onDragUpdateItem(
1798
- this.visibleStart,
1799
- this.visibleStart + this.visibleRangeWithPadding - 1
1800
- );
1801
- this._updateFocusByDragInfo(msg["viewX"], msg["viewY"]);
1802
- return true;
1803
- },
1804
- OnFling: (msg) => {
1805
- this.$refs.rootView?.updatePosition(msg["viewX"], msg["viewY"], null);
1806
- this.preUpdateVisibleStart = this.visibleStart;
1807
- this._onDragUpdateItem(
1808
- this.visibleStart,
1809
- this.visibleStart + this.visibleRangeWithPadding - 1
1810
- );
1811
- this._updateFocusByDragInfo(msg["viewX"], msg["viewY"]);
1812
- return true;
1813
- },
1814
- OnRelease: (msg) => {
1815
- return true;
1816
- },
1817
- };
1818
- return callback;
1546
+ return true;
1819
1547
  },
1820
- _getFocusBlockActions() {
1821
- return {
1822
- onFocus: this._onFocus,
1823
- onBlur: this._onBlur,
1824
- onKeyDown: this.onKeyDown,
1825
- onCustomerEvent: this._onCustomerEvent,
1826
- };
1548
+ OnDragEnd: (msg) => {
1549
+ _updatePosition(msg["viewX"], msg["viewY"], null);
1550
+ preUpdateVisibleStart = visibleInfo.start;
1551
+ _onDragUpdateItem(
1552
+ visibleInfo.startWithPadding,
1553
+ visibleInfo.endWithPadding
1554
+ );
1555
+ _updateFocusByDragInfo(msg["viewX"], msg["viewY"]);
1556
+ return true;
1827
1557
  },
1828
- _updatePage(range_list) {
1829
- let list = [];
1830
- for (let range of range_list) {
1831
- list = list.concat(this.innerData.slice(range.start, range.end + 1));
1832
- }
1833
- this.$refs.rootView?.updateData(list);
1834
- this.refreshToken++;
1835
- this.itemRender = false;
1836
- clearTimeout(this.updateTimerHandler);
1837
- this.updateTimerHandler = setTimeout(() => {
1838
- this.itemRender = true;
1839
- }, 0);
1558
+ OnFling: (msg) => {
1559
+ _updatePosition(msg["viewX"], msg["viewY"], null);
1560
+ preUpdateVisibleStart = visibleInfo.start;
1561
+ _onDragUpdateItem(
1562
+ visibleInfo.startWithPadding,
1563
+ visibleInfo.endWithPadding
1564
+ );
1565
+ _updateFocusByDragInfo(msg["viewX"], msg["viewY"]);
1566
+ return true;
1840
1567
  },
1841
- },
1842
- created() {
1843
- this.pageUpdater = new PageUpdater(this._updatePage);
1844
- if (this.dispatcher) {
1845
- this.dispatcher.registerComponent(this);
1846
- }
1847
- this.innerPadding = _getPadding(this.padding);
1848
- this.dragDirection =
1849
- this.direction === VERTICAL
1850
- ? Forge.DragSetting.DIRECTION_VERTICAL
1851
- : Forge.DragSetting.DIRECTION_HORIZONTAL;
1852
- this.visibleRange =
1853
- this.direction === VERTICAL
1854
- ? this.height - this.innerPadding.top - this.innerPadding.bottom
1855
- : this.width - this.innerPadding.left - this.innerPadding.right;
1856
- this.visibleRangeWithPadding =
1857
- this.direction === VERTICAL ? this.height : this.width;
1858
-
1859
- if (this.provideData) {
1860
- this.dataList = this.provideData();
1861
- } else if (this.data) {
1862
- this.dataList = this.data;
1863
- }
1568
+ OnRelease: (msg) => {
1569
+ return true;
1570
+ },
1571
+ };
1572
+ return callback;
1573
+ };
1864
1574
 
1865
- this.templateParser = _getTemplateParser(
1866
- this.width,
1867
- this.height,
1868
- this.direction,
1869
- this.padding,
1870
- this.supportHistoryPath,
1871
- this.layoutType
1872
- );
1873
- this.templateItemAdder = new TemplateItemAdder(
1874
- this.templateParser,
1875
- this.dataList,
1876
- this.measures,
1877
- this.visibleRangeWithPadding,
1878
- this._onTemplateAdd
1879
- );
1880
- this.templateItemAdder.tryAddItem(null, 2);
1881
- let template_list = this.templateParser.GetTemplate().List;
1882
- let last_item = template_list[template_list.length - 1];
1883
- if (last_item) {
1884
- this.touchListener = this._getTouchListener();
1885
- this.touchContainerW =
1886
- this.direction === VERTICAL
1887
- ? this.width
1888
- : last_item.xPos + last_item.width;
1889
- this.touchContainerH =
1890
- this.direction === VERTICAL
1891
- ? last_item.yPos + last_item.height
1892
- : this.height;
1893
- }
1894
- this.slidePile = new Forge.RectArea(
1895
- 0,
1896
- 0,
1897
- this.width - this.innerPadding.left - this.innerPadding.right,
1898
- this.height - this.innerPadding.top - this.innerPadding.bottom
1899
- );
1900
- let init_focus_id = 0;
1901
- let cur_visible_start = 0;
1902
-
1903
- if (this.initFocusId) {
1904
- this.templateItemAdder.tryAddItemById(this.initFocusId);
1905
- const item = this.templateParser.GetItemById(this.initFocusId);
1906
- if (item) {
1907
- init_focus_id = this.initFocusId;
1908
- cur_visible_start = this._calculateVisibleStart(item, 1);
1909
- }
1575
+ const _updatePage = (range_list) => {
1576
+ let list = [];
1577
+ for (let range of range_list) {
1578
+ list = list.concat(innerData.slice(range.start, range.end + 1));
1579
+ }
1580
+ renderData.value = list;
1581
+ if (props.enableItemRenderBreak) {
1582
+ itemRender.value = false;
1583
+ nextTick(() => {
1584
+ itemRender.value = true;
1585
+ });
1586
+ }
1587
+ };
1588
+
1589
+ const _onScroll = () => {
1590
+ if (props.onScroll) {
1591
+ const lastItem = templateParser.GetItem(-1);
1592
+ let totalWidth;
1593
+ if (vertical) {
1594
+ totalWidth = lastItem.yPos + lastItem.height - 1;
1595
+ } else {
1596
+ totalWidth = lastItem.xPos + lastItem.width - 1;
1910
1597
  }
1911
- this.focusId = init_focus_id;
1912
- this.visibleStart = cur_visible_start;
1913
- },
1914
- mounted() {
1915
- if (this.visibleStart) {
1916
- this._slideTo(this.visibleStart, null);
1598
+ props.onScroll(visibleInfo.start, visibleInfo.range, totalWidth);
1599
+ }
1600
+ };
1601
+
1602
+ //之前rootview相关的代码
1603
+ const _updatePosition = (x, y, anim_info) => {
1604
+ if (toRaw(slideDiv.value)) {
1605
+ let pre_pos = toRaw(slideDiv.value).jsvMaskView.GetLayoutParams();
1606
+ //jsvMaskView的位置更新时会被设置位0,因此不能通过ResetLayoutParams设置位置
1607
+ slideDivLeft.value = x;
1608
+ slideDivTop.value = y;
1609
+ if (anim_info) {
1610
+ let delta_x = Math.abs(pre_pos.MarginLeft - x);
1611
+ let delta_y = Math.abs(pre_pos.MarginTop - y);
1612
+ let duration = Math.round(
1613
+ delta_x === 0 ? delta_y / anim_info.speed : delta_x / anim_info.speed
1614
+ );
1615
+ let slide_animation = new Forge.TranslateAnimation(
1616
+ pre_pos.MarginLeft - x,
1617
+ 0,
1618
+ pre_pos.MarginTop - y,
1619
+ 0,
1620
+ duration,
1621
+ anim_info.easing
1622
+ );
1623
+ slide_animation.SetAnimationListener(
1624
+ new Forge.AnimationListener(anim_info.onstart, anim_info.onend, null)
1625
+ );
1626
+ toRaw(slideDiv.value).jsvMaskView.StartAnimation(slide_animation);
1917
1627
  }
1918
- this.pageUpdater.update(
1919
- this.templateParser,
1920
- this.visibleStart,
1921
- this.visibleStart + this.visibleRangeWithPadding - 1,
1922
- 0,
1628
+ _onScroll();
1629
+ }
1630
+ };
1631
+
1632
+ const _initRootTouch = () => {
1633
+ if (props.enableTouch && toRaw(slideDiv.value)) {
1634
+ let view = toRaw(slideDiv.value).jsvMaskView;
1635
+ var drag_setting = new Forge.DragSetting(
1636
+ dragDirection,
1637
+ 20,
1923
1638
  false,
1924
- this.permanentItemList
1639
+ slidePile,
1640
+ props.flingPageWidth,
1641
+ props.flingPageEdge
1925
1642
  );
1926
- this.pageUpdater.apply();
1927
- this.mounted = true;
1928
- },
1929
- beforeUnmount() {
1930
- this.mounted = false;
1931
- if (this.dispatcher) {
1932
- this.dispatcher.unregisterComponent();
1643
+ view.EnableDrag(drag_setting, touchListener, "translateMat(dx,dy,0)");
1644
+ }
1645
+ };
1646
+
1647
+ const _initItemViewTouch = (itemDivRef, index) => {
1648
+ if (props.enableTouch) {
1649
+ if (itemDivRef) {
1650
+ // 为view添加触控处理
1651
+ let view = itemDivRef.jsvMaskView;
1652
+ let dragSetting = new Forge.DragSetting(
1653
+ Forge.DragSetting.DIRECTION_DISABLE,
1654
+ 20,
1655
+ false,
1656
+ new Forge.RectArea(0, 0, 0, 0),
1657
+ -1,
1658
+ 3 / 4
1659
+ );
1660
+ let callback = {
1661
+ OnTap: (msg) => {
1662
+ return onItemClick(index);
1663
+ },
1664
+ };
1665
+ view.EnableDrag(dragSetting, callback, "translateMat(dx,dy,0)");
1933
1666
  }
1934
- clearTimeout(this.updateTimerHandler);
1935
- },
1667
+ }
1936
1668
  };
1937
1669
 
1938
- export default MetroWidget;
1670
+ //init
1671
+ pageUpdater = new PageUpdater(_updatePage);
1672
+ if (props.dispatcher) {
1673
+ props.dispatcher.registerComponent(exportObject);
1674
+ }
1675
+ innerPadding = _getPadding(props.padding);
1676
+ dragDirection = vertical
1677
+ ? Forge.DragSetting.DIRECTION_VERTICAL
1678
+ : Forge.DragSetting.DIRECTION_HORIZONTAL;
1679
+ visibleInfo.range = vertical
1680
+ ? props.height - innerPadding.top - innerPadding.bottom
1681
+ : props.width - innerPadding.left - innerPadding.right;
1682
+ visibleInfo.padding = vertical
1683
+ ? { start: innerPadding.top, end: innerPadding.bottom }
1684
+ : { start: innerPadding.left, end: innerPadding.right };
1685
+
1686
+ if (props.provideData) {
1687
+ dataList = toRaw(props.provideData());
1688
+ } else if (props.data) {
1689
+ dataList = toRaw(props.data);
1690
+ }
1691
+
1692
+ templateParser = _getTemplateParser(
1693
+ props.width,
1694
+ props.height,
1695
+ props.direction,
1696
+ props.padding,
1697
+ props.supportHistoryPath,
1698
+ props.layoutType
1699
+ );
1700
+ templateItemAdder = new TemplateItemAdder(
1701
+ templateParser,
1702
+ dataList,
1703
+ props.measures,
1704
+ pageRange,
1705
+ _onTemplateAdd
1706
+ );
1707
+ if (props.onScroll) {
1708
+ templateItemAdder.tryAddItemByIndex(dataList.length - 1);
1709
+ } else {
1710
+ templateItemAdder.tryAddItem(null, 2);
1711
+ }
1712
+
1713
+ let template_list = templateParser.GetTemplate().List;
1714
+
1715
+ //触控相关
1716
+ let last_item = template_list[template_list.length - 1];
1717
+ if (last_item) {
1718
+ touchListener = _getTouchListener();
1719
+ touchContainerW.value =
1720
+ props.direction === VERTICAL
1721
+ ? props.width
1722
+ : last_item.xPos + last_item.width;
1723
+ touchContainerH.value =
1724
+ props.direction === VERTICAL
1725
+ ? last_item.yPos + last_item.height
1726
+ : props.height;
1727
+ }
1728
+ slidePile = new Forge.RectArea(
1729
+ 0,
1730
+ 0,
1731
+ props.width - innerPadding.left - innerPadding.right,
1732
+ props.height - innerPadding.top - innerPadding.bottom
1733
+ );
1734
+ let init_focus_id = 0;
1735
+ let cur_visible_start = 0;
1736
+
1737
+ if (props.initFocusId) {
1738
+ templateItemAdder.tryAddItemById(props.initFocusId);
1739
+ const item = templateParser.GetItemById(props.initFocusId);
1740
+ if (item) {
1741
+ init_focus_id = props.initFocusId;
1742
+ cur_visible_start = _calculateVisibleStart(item, 1);
1743
+ }
1744
+ }
1745
+ focusId = init_focus_id;
1746
+ visibleInfo.start = cur_visible_start;
1747
+
1748
+ pageUpdater.update(
1749
+ templateParser,
1750
+ visibleInfo.startWithPadding,
1751
+ visibleInfo.endWithPadding,
1752
+ 0,
1753
+ false,
1754
+ permanentItemList
1755
+ );
1756
+ let list = [];
1757
+ for (let range of pageUpdater.rangeList) {
1758
+ list = list.concat(innerData.slice(range.start, range.end + 1));
1759
+ }
1760
+ renderData.value = list;
1761
+
1762
+ onMounted(() => {
1763
+ mounted = true;
1764
+ _initRootTouch();
1765
+ for (let item of renderData.value) {
1766
+ _initItemViewTouch(toRaw(item.itemDivRef), item.index);
1767
+ }
1768
+
1769
+ if (visibleInfo.start) {
1770
+ _slideTo(visibleInfo.start, null);
1771
+ }
1772
+
1773
+ onItemFocus(templateParser.FocusIdToIndex(focusId), preEdgeRect);
1774
+
1775
+ if (props.enableItemRenderBreak) {
1776
+ nextTick(() => {
1777
+ itemRender.value = true;
1778
+ });
1779
+ }
1780
+ });
1781
+
1782
+ onUpdated(() => {
1783
+ for (let item of renderData.value) {
1784
+ if (!item.touchInited) {
1785
+ _initItemViewTouch(toRaw(item.itemDivRef), item.index);
1786
+ }
1787
+ }
1788
+ });
1789
+
1790
+ onBeforeUnmount(() => {
1791
+ mounted = false;
1792
+ if (props.dispatcher) {
1793
+ props.dispatcher.unregisterComponent();
1794
+ }
1795
+ });
1796
+
1797
+ defineExpose(exportObject);
1939
1798
  </script>
1940
1799
 
1941
1800
  <template>
1942
- <jsv-focus-block
1943
- ref="focusNode"
1944
- :name="name"
1945
- :onAction="_getFocusBlockActions()"
1801
+ <div
1802
+ :style="{
1803
+ left: left,
1804
+ top: top,
1805
+ width: width,
1806
+ height: height,
1807
+ overflow: 'hidden',
1808
+ }"
1946
1809
  >
1947
- <div
1948
- ref="rootDiv"
1949
- :style="{
1950
- left: left,
1951
- top: top,
1952
- width: width,
1953
- height: height,
1954
- overflow: 'hidden',
1955
- }"
1956
- >
1957
- <root-view
1958
- ref="rootView"
1959
- :refreshToken="refreshToken"
1960
- :dataUpdateToken="dataUpdateToken"
1961
- :x="innerPadding.left"
1962
- :y="innerPadding.top"
1963
- :width="touchContainerW"
1964
- :height="touchContainerH"
1965
- :flingPageWidth="flingPageWidth"
1966
- :flingPageEdge="flingPageEdge"
1967
- :slidePile="slidePile"
1968
- :direction="dragDirection"
1969
- :touchListener="touchListener"
1970
- :enableTouch="enableTouch"
1971
- :loadAll="loadAll"
1972
- :register="_registerRootView"
1973
- :onLoad="_onContentUpdate"
1974
- :onItemEdge="_onFocusableItemEdge"
1975
- :widgetHandler="_injectHandler()"
1976
- :enableItemRenderBreak="enableItemRenderBreak"
1977
- :placeHolderSetting="placeHolderSetting"
1810
+ <div :style="{ left: innerPadding.left, top: innerPadding.top }">
1811
+ <div
1812
+ key="touchcontainer"
1813
+ ref="slideDiv"
1814
+ :style="{
1815
+ left: slideDivLeft,
1816
+ top: slideDivTop,
1817
+ width: touchContainerW,
1818
+ height: touchContainerH,
1819
+ }"
1978
1820
  >
1979
- <template v-slot:renderItem="slotProps">
1980
- <slot name="renderItem" v-bind="slotProps"></slot>
1981
- </template>
1982
- </root-view>
1821
+ <div ref="locateDiv">
1822
+ <jsv-focus-block
1823
+ ref="focusNode"
1824
+ :name="name"
1825
+ :onAction="{
1826
+ onFocus: _onFocus,
1827
+ onBlur: _onBlur,
1828
+ onKeyDown: onKeyDown,
1829
+ onCustomerEvent: _onCustomerEvent,
1830
+ }"
1831
+ >
1832
+ <div
1833
+ v-for="item in renderData"
1834
+ :key="pageUpdateToken + '_' + item.index"
1835
+ :ref="item.refCallback"
1836
+ :style="{
1837
+ left: item.data.xPos,
1838
+ top: item.data.yPos,
1839
+ width: item.data.width,
1840
+ height: item.data.height,
1841
+ zIndex: item.controller.zIndex,
1842
+ }"
1843
+ >
1844
+ <div
1845
+ v-if="
1846
+ !enableItemRenderBreak || item.slotMounted.value || itemRender
1847
+ "
1848
+ :key="renderBreakKey"
1849
+ :ref="item.slotDivRef"
1850
+ >
1851
+ <slot
1852
+ name="renderItem"
1853
+ :key="renderBreakKey"
1854
+ :data="item.data.data"
1855
+ :onEdge="_onFocusableItemEdge"
1856
+ :onAction="item.register"
1857
+ :query="item.query"
1858
+ :onItemEdge="_onFocusableItemEdge"
1859
+ ></slot>
1860
+ </div>
1861
+ <div
1862
+ v-if="
1863
+ enableItemRenderBreak &&
1864
+ placeHolderSetting &&
1865
+ !item.slotMounted.value
1866
+ "
1867
+ :style="{
1868
+ width:
1869
+ item.data.width -
1870
+ (placeHolderSetting.gap ? placeHolderSetting.gap : 0),
1871
+ height:
1872
+ item.data.height -
1873
+ (placeHolderSetting.gap ? placeHolderSetting.gap : 0),
1874
+ backgroundColor: placeHolderSetting.backgroundColor,
1875
+ borderRadius: placeHolderSetting.borderRadius,
1876
+ }"
1877
+ ></div>
1878
+ </div>
1879
+ </jsv-focus-block>
1880
+ </div>
1881
+ </div>
1983
1882
  </div>
1984
- </jsv-focus-block>
1883
+ </div>
1985
1884
  </template>