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