pythonnative 0.40.0__cp313-cp313-win_amd64.whl

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 (418) hide show
  1. pythonnative/__init__.py +411 -0
  2. pythonnative/_ios_log.py +92 -0
  3. pythonnative/_yoga.cp313-win_amd64.pyd +0 -0
  4. pythonnative/alerts.py +236 -0
  5. pythonnative/animated.py +1687 -0
  6. pythonnative/animation_graph.py +78 -0
  7. pythonnative/appearance.py +124 -0
  8. pythonnative/bootstrap.py +100 -0
  9. pythonnative/bridge/__init__.py +302 -0
  10. pythonnative/bridge/android.py +78 -0
  11. pythonnative/bridge/codec.py +170 -0
  12. pythonnative/bridge/commits.py +114 -0
  13. pythonnative/bridge/fake.py +243 -0
  14. pythonnative/bridge/ios.py +138 -0
  15. pythonnative/bridge/web.py +489 -0
  16. pythonnative/cli/__init__.py +7 -0
  17. pythonnative/cli/pn.py +1214 -0
  18. pythonnative/component.py +271 -0
  19. pythonnative/components/__init__.py +111 -0
  20. pythonnative/components/_base.py +166 -0
  21. pythonnative/components/controls.py +521 -0
  22. pythonnative/components/layout.py +518 -0
  23. pythonnative/components/lists.py +785 -0
  24. pythonnative/components/media.py +204 -0
  25. pythonnative/components/overlays.py +107 -0
  26. pythonnative/components/pressable.py +252 -0
  27. pythonnative/components/structural.py +167 -0
  28. pythonnative/components/text.py +291 -0
  29. pythonnative/devclient.py +824 -0
  30. pythonnative/devserver/__init__.py +34 -0
  31. pythonnative/devserver/server.py +718 -0
  32. pythonnative/devserver/static/animation_graph.js +82 -0
  33. pythonnative/devserver/static/bridge.js +147 -0
  34. pythonnative/devserver/static/colors.js +70 -0
  35. pythonnative/devserver/static/host.js +552 -0
  36. pythonnative/devserver/static/index.html +60 -0
  37. pythonnative/devserver/static/layout.js +85 -0
  38. pythonnative/devserver/static/preview.css +415 -0
  39. pythonnative/devserver/static/renderer.js +1994 -0
  40. pythonnative/devserver/static/shell.js +345 -0
  41. pythonnative/devserver/static/yoga/LICENSE +21 -0
  42. pythonnative/devserver/static/yoga/binaries/yoga-wasm-base64-esm.js +75 -0
  43. pythonnative/devserver/static/yoga/src/generated/YGEnums.d.ts +189 -0
  44. pythonnative/devserver/static/yoga/src/generated/YGEnums.js +211 -0
  45. pythonnative/devserver/static/yoga/src/generated/YGEnums.js.map +1 -0
  46. pythonnative/devserver/static/yoga/src/index.d.ts +12 -0
  47. pythonnative/devserver/static/yoga/src/index.js +16 -0
  48. pythonnative/devserver/static/yoga/src/index.js.map +1 -0
  49. pythonnative/devserver/static/yoga/src/load.d.ts +11 -0
  50. pythonnative/devserver/static/yoga/src/load.js +17 -0
  51. pythonnative/devserver/static/yoga/src/load.js.map +1 -0
  52. pythonnative/devserver/static/yoga/src/wrapAssembly.d.ts +155 -0
  53. pythonnative/devserver/static/yoga/src/wrapAssembly.js +125 -0
  54. pythonnative/devserver/static/yoga/src/wrapAssembly.js.map +1 -0
  55. pythonnative/devserver/watcher.py +267 -0
  56. pythonnative/devserver/ws.py +421 -0
  57. pythonnative/diagnostics.py +241 -0
  58. pythonnative/element.py +159 -0
  59. pythonnative/equality.py +19 -0
  60. pythonnative/events.py +231 -0
  61. pythonnative/gestures.py +1333 -0
  62. pythonnative/hooks.py +1621 -0
  63. pythonnative/hosts/__init__.py +63 -0
  64. pythonnative/hosts/base.py +596 -0
  65. pythonnative/hosts/native.py +302 -0
  66. pythonnative/hot_reload.py +585 -0
  67. pythonnative/layout.py +328 -0
  68. pythonnative/mutations.py +142 -0
  69. pythonnative/native/android/build.gradle +52 -0
  70. pythonnative/native/android/gradle.properties +3 -0
  71. pythonnative/native/android/settings.gradle +12 -0
  72. pythonnative/native/android/src/main/AndroidManifest.xml +11 -0
  73. pythonnative/native/android/src/main/cpp/CMakeLists.txt +9 -0
  74. pythonnative/native/android/src/main/cpp/yoga_jni.cpp +52 -0
  75. pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeModules.kt +5 -0
  76. pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeProps.kt +3705 -0
  77. pythonnative/native/android/src/main/java/com/pythonnative/generated/PNContracts.kt +129 -0
  78. pythonnative/native/android/src/main/java/com/pythonnative/runtime/PNBridge.kt +261 -0
  79. pythonnative/native/android/src/main/java/com/pythonnative/runtime/PythonHost.kt +20 -0
  80. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationGraph.kt +108 -0
  81. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationSpecs.kt +141 -0
  82. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/PNAnimator.kt +257 -0
  83. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/CommitState.kt +106 -0
  84. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/JsonUtil.kt +175 -0
  85. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/MainThread.kt +40 -0
  86. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNLog.kt +33 -0
  87. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNRegistry.kt +82 -0
  88. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNTransaction.kt +80 -0
  89. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/TransactionApplier.kt +117 -0
  90. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/ViewRegistry.kt +74 -0
  91. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/BuiltinComponents.kt +37 -0
  92. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ButtonManager.kt +32 -0
  93. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ComponentManager.kt +213 -0
  94. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ContainerManagers.kt +69 -0
  95. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ControlManagers.kt +186 -0
  96. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/DatePickerManager.kt +123 -0
  97. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageLoader.kt +141 -0
  98. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageManager.kt +162 -0
  99. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ModalManager.kt +134 -0
  100. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PNColor.kt +201 -0
  101. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PickerManager.kt +86 -0
  102. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PortalManager.kt +55 -0
  103. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PressableManager.kt +122 -0
  104. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScreenStackManager.kt +110 -0
  105. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScrollViewManager.kt +214 -0
  106. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/SegmentedControlManager.kt +113 -0
  107. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/StatusBarManager.kt +52 -0
  108. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TabBarManager.kt +131 -0
  109. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextInputManager.kt +250 -0
  110. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextManager.kt +233 -0
  111. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ViewStyler.kt +355 -0
  112. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/VirtualListManager.kt +159 -0
  113. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/WebViewManager.kt +149 -0
  114. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureArbiter.kt +233 -0
  115. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureCoordinator.kt +127 -0
  116. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureRecognizers.kt +527 -0
  117. pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/NativeLayout.kt +145 -0
  118. pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/YogaNode.kt +29 -0
  119. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/BuiltinModules.kt +73 -0
  120. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/DeviceModules.kt +316 -0
  121. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/HostModule.kt +61 -0
  122. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/MediaModules.kt +200 -0
  123. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NativeModule.kt +158 -0
  124. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NotificationsModule.kt +100 -0
  125. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/PermissionsModule.kt +99 -0
  126. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/StorageModules.kt +89 -0
  127. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/SystemModules.kt +178 -0
  128. pythonnative/native/android/src/main/java/com/pythonnative/runtime/plugins/GeneratedPlugins.kt +16 -0
  129. pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/PNScreenFragment.kt +188 -0
  130. pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/ScreenRegistry.kt +80 -0
  131. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNAccessibilityDelegate.kt +48 -0
  132. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNBorderDrawable.kt +76 -0
  133. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNEditText.kt +18 -0
  134. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNFrameLayout.kt +49 -0
  135. pythonnative/native/android/src/test/java/com/pythonnative/runtime/AnimationSpecsTest.kt +75 -0
  136. pythonnative/native/android/src/test/java/com/pythonnative/runtime/GestureArbiterTest.kt +197 -0
  137. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNColorTest.kt +47 -0
  138. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNTransactionTest.kt +78 -0
  139. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PromiseTest.kt +89 -0
  140. pythonnative/native/ios/Package.swift +23 -0
  141. pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimationGraph.swift +199 -0
  142. pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimator.swift +312 -0
  143. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNBridge.swift +255 -0
  144. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNCommit.swift +104 -0
  145. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNRegistry.swift +142 -0
  146. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNTransaction.swift +166 -0
  147. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNViewRegistry.swift +53 -0
  148. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNButtonManagers.swift +207 -0
  149. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNColor.swift +173 -0
  150. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNComponentManager.swift +183 -0
  151. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNContainerView.swift +56 -0
  152. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNControlManagers.swift +281 -0
  153. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNImageManager.swift +222 -0
  154. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNOverlayManagers.swift +243 -0
  155. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNPressableManager.swift +114 -0
  156. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScreenStackManager.swift +107 -0
  157. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScrollViewManager.swift +197 -0
  158. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTabBarManager.swift +106 -0
  159. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextInputManager.swift +297 -0
  160. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextManager.swift +230 -0
  161. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTransform.swift +82 -0
  162. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewManager.swift +86 -0
  163. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewState.swift +87 -0
  164. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewStyler.swift +340 -0
  165. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNVirtualListManager.swift +155 -0
  166. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNWebViewManager.swift +124 -0
  167. pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeModules.swift +1 -0
  168. pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeProps.swift +3775 -0
  169. pythonnative/native/ios/Sources/PythonNativeKit/Generated/PNContracts.swift +46 -0
  170. pythonnative/native/ios/Sources/PythonNativeKit/Gestures/PNGestureCoordinator.swift +260 -0
  171. pythonnative/native/ios/Sources/PythonNativeKit/Layout/PNLayout.swift +173 -0
  172. pythonnative/native/ios/Sources/PythonNativeKit/Modules/AlertModule.swift +92 -0
  173. pythonnative/native/ios/Sources/PythonNativeKit/Modules/HostModule.swift +80 -0
  174. pythonnative/native/ios/Sources/PythonNativeKit/Modules/LifecycleModules.swift +174 -0
  175. pythonnative/native/ios/Sources/PythonNativeKit/Modules/MediaModules.swift +177 -0
  176. pythonnative/native/ios/Sources/PythonNativeKit/Modules/PNNativeModule.swift +168 -0
  177. pythonnative/native/ios/Sources/PythonNativeKit/Modules/PermissionModules.swift +266 -0
  178. pythonnative/native/ios/Sources/PythonNativeKit/Modules/SystemModules.swift +251 -0
  179. pythonnative/native/ios/Sources/PythonNativeKit/Plugins/PNPluginRegistration.swift +8 -0
  180. pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNScreenRegistry.swift +46 -0
  181. pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNViewController.swift +237 -0
  182. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNCompat.swift +46 -0
  183. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNJSON.swift +173 -0
  184. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNLog.swift +47 -0
  185. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNWindow.swift +51 -0
  186. pythonnative/native/ios/Tests/PythonNativeKitTests/PNAnimationGraphTests.swift +26 -0
  187. pythonnative/native/ios/Tests/PythonNativeKitTests/PNColorTests.swift +50 -0
  188. pythonnative/native/ios/Tests/PythonNativeKitTests/PNCommitTests.swift +86 -0
  189. pythonnative/native/ios/Tests/PythonNativeKitTests/PNGestureTests.swift +101 -0
  190. pythonnative/native/ios/Tests/PythonNativeKitTests/PNManagerTests.swift +126 -0
  191. pythonnative/native/ios/Tests/PythonNativeKitTests/PNModuleTests.swift +111 -0
  192. pythonnative/native/ios/Tests/PythonNativeKitTests/PNTransactionTests.swift +91 -0
  193. pythonnative/native/yoga/LICENSE +21 -0
  194. pythonnative/native/yoga/Package.swift +9 -0
  195. pythonnative/native/yoga/VENDORED.md +2 -0
  196. pythonnative/native/yoga/include/PNStyle.h +10 -0
  197. pythonnative/native/yoga/include/module.modulemap +5 -0
  198. pythonnative/native/yoga/include/yoga/YGConfig.h +158 -0
  199. pythonnative/native/yoga/include/yoga/YGEnums.h +142 -0
  200. pythonnative/native/yoga/include/yoga/YGMacros.h +99 -0
  201. pythonnative/native/yoga/include/yoga/YGNode.h +304 -0
  202. pythonnative/native/yoga/include/yoga/YGNodeLayout.h +35 -0
  203. pythonnative/native/yoga/include/yoga/YGNodeStyle.h +130 -0
  204. pythonnative/native/yoga/include/yoga/YGPixelGrid.h +29 -0
  205. pythonnative/native/yoga/include/yoga/YGValue.h +84 -0
  206. pythonnative/native/yoga/include/yoga/Yoga.h +21 -0
  207. pythonnative/native/yoga/python.cpp +16 -0
  208. pythonnative/native/yoga/style.cpp +272 -0
  209. pythonnative/native/yoga/yoga/CMakeLists.txt +41 -0
  210. pythonnative/native/yoga/yoga/YGConfig.cpp +92 -0
  211. pythonnative/native/yoga/yoga/YGConfig.h +158 -0
  212. pythonnative/native/yoga/yoga/YGEnums.cpp +262 -0
  213. pythonnative/native/yoga/yoga/YGEnums.h +142 -0
  214. pythonnative/native/yoga/yoga/YGMacros.h +99 -0
  215. pythonnative/native/yoga/yoga/YGNode.cpp +366 -0
  216. pythonnative/native/yoga/yoga/YGNode.h +304 -0
  217. pythonnative/native/yoga/yoga/YGNodeLayout.cpp +92 -0
  218. pythonnative/native/yoga/yoga/YGNodeLayout.h +35 -0
  219. pythonnative/native/yoga/yoga/YGNodeStyle.cpp +405 -0
  220. pythonnative/native/yoga/yoga/YGNodeStyle.h +130 -0
  221. pythonnative/native/yoga/yoga/YGPixelGrid.cpp +22 -0
  222. pythonnative/native/yoga/yoga/YGPixelGrid.h +29 -0
  223. pythonnative/native/yoga/yoga/YGValue.cpp +20 -0
  224. pythonnative/native/yoga/yoga/YGValue.h +84 -0
  225. pythonnative/native/yoga/yoga/Yoga.h +21 -0
  226. pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.cpp +563 -0
  227. pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.h +41 -0
  228. pythonnative/native/yoga/yoga/algorithm/Align.h +72 -0
  229. pythonnative/native/yoga/yoga/algorithm/Baseline.cpp +78 -0
  230. pythonnative/native/yoga/yoga/algorithm/Baseline.h +21 -0
  231. pythonnative/native/yoga/yoga/algorithm/BoundAxis.h +79 -0
  232. pythonnative/native/yoga/yoga/algorithm/Cache.cpp +121 -0
  233. pythonnative/native/yoga/yoga/algorithm/Cache.h +30 -0
  234. pythonnative/native/yoga/yoga/algorithm/CalculateLayout.cpp +2428 -0
  235. pythonnative/native/yoga/yoga/algorithm/CalculateLayout.h +38 -0
  236. pythonnative/native/yoga/yoga/algorithm/FlexDirection.h +120 -0
  237. pythonnative/native/yoga/yoga/algorithm/FlexLine.cpp +124 -0
  238. pythonnative/native/yoga/yoga/algorithm/FlexLine.h +75 -0
  239. pythonnative/native/yoga/yoga/algorithm/PixelGrid.cpp +132 -0
  240. pythonnative/native/yoga/yoga/algorithm/PixelGrid.h +29 -0
  241. pythonnative/native/yoga/yoga/algorithm/SizingMode.h +73 -0
  242. pythonnative/native/yoga/yoga/algorithm/TrailingPosition.h +44 -0
  243. pythonnative/native/yoga/yoga/config/Config.cpp +135 -0
  244. pythonnative/native/yoga/yoga/config/Config.h +92 -0
  245. pythonnative/native/yoga/yoga/debug/AssertFatal.cpp +53 -0
  246. pythonnative/native/yoga/yoga/debug/AssertFatal.h +29 -0
  247. pythonnative/native/yoga/yoga/debug/Log.cpp +107 -0
  248. pythonnative/native/yoga/yoga/debug/Log.h +34 -0
  249. pythonnative/native/yoga/yoga/enums/Align.h +47 -0
  250. pythonnative/native/yoga/yoga/enums/BoxSizing.h +40 -0
  251. pythonnative/native/yoga/yoga/enums/Dimension.h +40 -0
  252. pythonnative/native/yoga/yoga/enums/Direction.h +41 -0
  253. pythonnative/native/yoga/yoga/enums/Display.h +41 -0
  254. pythonnative/native/yoga/yoga/enums/Edge.h +47 -0
  255. pythonnative/native/yoga/yoga/enums/Errata.h +41 -0
  256. pythonnative/native/yoga/yoga/enums/ExperimentalFeature.h +39 -0
  257. pythonnative/native/yoga/yoga/enums/FlexDirection.h +42 -0
  258. pythonnative/native/yoga/yoga/enums/Gutter.h +41 -0
  259. pythonnative/native/yoga/yoga/enums/Justify.h +44 -0
  260. pythonnative/native/yoga/yoga/enums/LogLevel.h +44 -0
  261. pythonnative/native/yoga/yoga/enums/MeasureMode.h +41 -0
  262. pythonnative/native/yoga/yoga/enums/NodeType.h +40 -0
  263. pythonnative/native/yoga/yoga/enums/Overflow.h +41 -0
  264. pythonnative/native/yoga/yoga/enums/PhysicalEdge.h +21 -0
  265. pythonnative/native/yoga/yoga/enums/PositionType.h +41 -0
  266. pythonnative/native/yoga/yoga/enums/Unit.h +42 -0
  267. pythonnative/native/yoga/yoga/enums/Wrap.h +41 -0
  268. pythonnative/native/yoga/yoga/enums/YogaEnums.h +85 -0
  269. pythonnative/native/yoga/yoga/event/event.cpp +87 -0
  270. pythonnative/native/yoga/yoga/event/event.h +130 -0
  271. pythonnative/native/yoga/yoga/module.modulemap +21 -0
  272. pythonnative/native/yoga/yoga/node/CachedMeasurement.h +53 -0
  273. pythonnative/native/yoga/yoga/node/LayoutResults.cpp +48 -0
  274. pythonnative/native/yoga/yoga/node/LayoutResults.h +122 -0
  275. pythonnative/native/yoga/yoga/node/LayoutableChildren.h +148 -0
  276. pythonnative/native/yoga/yoga/node/Node.cpp +443 -0
  277. pythonnative/native/yoga/yoga/node/Node.h +337 -0
  278. pythonnative/native/yoga/yoga/numeric/Comparison.h +81 -0
  279. pythonnative/native/yoga/yoga/numeric/FloatOptional.h +93 -0
  280. pythonnative/native/yoga/yoga/style/SmallValueBuffer.h +133 -0
  281. pythonnative/native/yoga/yoga/style/Style.h +757 -0
  282. pythonnative/native/yoga/yoga/style/StyleLength.h +107 -0
  283. pythonnative/native/yoga/yoga/style/StyleValueHandle.h +98 -0
  284. pythonnative/native/yoga/yoga/style/StyleValuePool.h +127 -0
  285. pythonnative/native_modules/__init__.py +124 -0
  286. pythonnative/native_modules/app_state.py +99 -0
  287. pythonnative/native_modules/battery.py +75 -0
  288. pythonnative/native_modules/biometrics.py +42 -0
  289. pythonnative/native_modules/camera.py +65 -0
  290. pythonnative/native_modules/clipboard.py +46 -0
  291. pythonnative/native_modules/fallback.py +324 -0
  292. pythonnative/native_modules/file_system.py +145 -0
  293. pythonnative/native_modules/haptics.py +75 -0
  294. pythonnative/native_modules/linking.py +123 -0
  295. pythonnative/native_modules/location.py +75 -0
  296. pythonnative/native_modules/net_info.py +112 -0
  297. pythonnative/native_modules/notifications.py +129 -0
  298. pythonnative/native_modules/permissions.py +108 -0
  299. pythonnative/native_modules/registry.py +526 -0
  300. pythonnative/native_modules/secure_store.py +52 -0
  301. pythonnative/native_modules/share.py +51 -0
  302. pythonnative/native_views/__init__.py +375 -0
  303. pythonnative/native_views/base.py +316 -0
  304. pythonnative/native_views/bridge_backend.py +277 -0
  305. pythonnative/navigation/__init__.py +103 -0
  306. pythonnative/navigation/container.py +154 -0
  307. pythonnative/navigation/handle.py +540 -0
  308. pythonnative/navigation/hooks.py +133 -0
  309. pythonnative/navigation/host.py +58 -0
  310. pythonnative/navigation/linking.py +200 -0
  311. pythonnative/navigation/navigators.py +659 -0
  312. pythonnative/navigation/screen.py +149 -0
  313. pythonnative/navigation/state.py +269 -0
  314. pythonnative/net.py +248 -0
  315. pythonnative/platform.py +166 -0
  316. pythonnative/platform_metrics.py +252 -0
  317. pythonnative/preview.py +287 -0
  318. pythonnative/profiling.py +101 -0
  319. pythonnative/project/__init__.py +68 -0
  320. pythonnative/project/android.py +557 -0
  321. pythonnative/project/builder.py +817 -0
  322. pythonnative/project/config.py +773 -0
  323. pythonnative/project/deps.py +719 -0
  324. pythonnative/project/devices.py +304 -0
  325. pythonnative/project/doctor.py +283 -0
  326. pythonnative/project/fingerprint.py +171 -0
  327. pythonnative/project/icons.py +247 -0
  328. pythonnative/project/ios.py +325 -0
  329. pythonnative/project/lockfile.py +100 -0
  330. pythonnative/project/permissions.py +361 -0
  331. pythonnative/project/plugins.py +519 -0
  332. pythonnative/project/runtime_assets.py +183 -0
  333. pythonnative/py.typed +0 -0
  334. pythonnative/query.py +153 -0
  335. pythonnative/reconciler/__init__.py +29 -0
  336. pythonnative/reconciler/boundaries.py +375 -0
  337. pythonnative/reconciler/children.py +88 -0
  338. pythonnative/reconciler/core.py +1165 -0
  339. pythonnative/reconciler/layout_pass.py +393 -0
  340. pythonnative/reconciler/vnode.py +266 -0
  341. pythonnative/refresh.py +55 -0
  342. pythonnative/runtime.py +306 -0
  343. pythonnative/scheduler.py +159 -0
  344. pythonnative/sdk/__init__.py +153 -0
  345. pythonnative/sdk/_components.py +427 -0
  346. pythonnative/sdk/builtins.py +91 -0
  347. pythonnative/sdk/codegen.py +149 -0
  348. pythonnative/sdk/module_codegen.py +184 -0
  349. pythonnative/sdk/schema.py +224 -0
  350. pythonnative/sdk/templates/contracts.kt +46 -0
  351. pythonnative/sdk/templates/contracts.swift +46 -0
  352. pythonnative/storage.py +184 -0
  353. pythonnative/style.py +841 -0
  354. pythonnative/suspense.py +183 -0
  355. pythonnative/templates/android_template/app/build.gradle +75 -0
  356. pythonnative/templates/android_template/app/proguard-rules.pro +21 -0
  357. pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt +24 -0
  358. pythonnative/templates/android_template/app/src/debug/AndroidManifest.xml +7 -0
  359. pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +32 -0
  360. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +130 -0
  361. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +13 -0
  362. pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
  363. pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +30 -0
  364. pythonnative/templates/android_template/app/src/main/res/layout/activity_main.xml +10 -0
  365. pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +6 -0
  366. pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +6 -0
  367. pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
  368. pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
  369. pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
  370. pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
  371. pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
  372. pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
  373. pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
  374. pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
  375. pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
  376. pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
  377. pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +22 -0
  378. pythonnative/templates/android_template/app/src/main/res/values/colors.xml +5 -0
  379. pythonnative/templates/android_template/app/src/main/res/values/strings.xml +5 -0
  380. pythonnative/templates/android_template/app/src/main/res/values/themes.xml +9 -0
  381. pythonnative/templates/android_template/app/src/main/res/values-night/themes.xml +7 -0
  382. pythonnative/templates/android_template/app/src/main/res/xml/backup_rules.xml +13 -0
  383. pythonnative/templates/android_template/app/src/main/res/xml/data_extraction_rules.xml +19 -0
  384. pythonnative/templates/android_template/app/src/test/java/com/pythonnative/android_template/ExampleUnitTest.kt +17 -0
  385. pythonnative/templates/android_template/build.gradle +10 -0
  386. pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.jar +0 -0
  387. pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +6 -0
  388. pythonnative/templates/android_template/gradle.properties +23 -0
  389. pythonnative/templates/android_template/gradlew +185 -0
  390. pythonnative/templates/android_template/gradlew.bat +89 -0
  391. pythonnative/templates/android_template/settings.gradle +17 -0
  392. pythonnative/templates/ios_template/ios_template/AppDelegate.swift +51 -0
  393. pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
  394. pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json +13 -0
  395. pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json +6 -0
  396. pythonnative/templates/ios_template/ios_template/Base.lproj/LaunchScreen.storyboard +25 -0
  397. pythonnative/templates/ios_template/ios_template/BridgingHeader.h +14 -0
  398. pythonnative/templates/ios_template/ios_template/Info.plist +28 -0
  399. pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +390 -0
  400. pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +61 -0
  401. pythonnative/templates/ios_template/ios_template/ViewController.swift +23 -0
  402. pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +745 -0
  403. pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  404. pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift +36 -0
  405. pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift +41 -0
  406. pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift +32 -0
  407. pythonnative/testing/__init__.py +53 -0
  408. pythonnative/testing/backend.py +276 -0
  409. pythonnative/testing/harness.py +369 -0
  410. pythonnative/utils.py +145 -0
  411. pythonnative-0.40.0.dist-info/DELVEWHEEL +2 -0
  412. pythonnative-0.40.0.dist-info/METADATA +150 -0
  413. pythonnative-0.40.0.dist-info/RECORD +418 -0
  414. pythonnative-0.40.0.dist-info/WHEEL +5 -0
  415. pythonnative-0.40.0.dist-info/entry_points.txt +2 -0
  416. pythonnative-0.40.0.dist-info/licenses/LICENSE +21 -0
  417. pythonnative-0.40.0.dist-info/top_level.txt +1 -0
  418. pythonnative.libs/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll +0 -0
@@ -0,0 +1,527 @@
1
+ package com.pythonnative.runtime.gestures
2
+
3
+ import kotlin.math.abs
4
+ import kotlin.math.atan2
5
+ import kotlin.math.hypot
6
+ import kotlin.math.max
7
+
8
+ /** Gesture states reported on event payloads. */
9
+ object GestureState {
10
+ const val BEGAN = "began"
11
+ const val CHANGED = "changed"
12
+ const val ENDED = "ended"
13
+ const val CANCELLED = "cancelled"
14
+
15
+ /** Internal verdict used by recognizers to tell the arbiter they cannot succeed. */
16
+ const val FAILED = "__failed"
17
+ }
18
+
19
+ /** A pointer position in the view's coordinate space, in dp. */
20
+ data class Point(val x: Double, val y: Double)
21
+
22
+ /** Output channel of recognizers and the arbiter: `(gesture_index, payload)`. */
23
+ typealias EmitFn = (Int, Map<String, Any?>) -> Unit
24
+
25
+ /** Configuration for one leaf gesture, decoded from the serialized `gestures` prop. */
26
+ data class GestureConfig(
27
+ val kind: String,
28
+ val nTaps: Int = 1,
29
+ val maxDistance: Double = 12.0,
30
+ val minDurationMs: Double = 500.0,
31
+ val minDistance: Double = 10.0,
32
+ val minPointers: Int = 1,
33
+ val direction: String = "any",
34
+ val minVelocity: Double = 300.0,
35
+ val nPointers: Int = 1,
36
+ /** Indices this gesture may be active alongside; `null` means everything. */
37
+ val simultaneous: Set<Int>? = null,
38
+ /** Indices that must fail before this gesture may activate. */
39
+ val waitFor: Set<Int> = emptySet(),
40
+ )
41
+
42
+ /** Estimate pointer velocity from recent samples (dp per second). */
43
+ class VelocityEstimator {
44
+ private data class Sample(val x: Double, val y: Double, val t: Double)
45
+
46
+ private val samples = ArrayList<Sample>()
47
+
48
+ fun add(x: Double, y: Double, t: Double) {
49
+ samples.add(Sample(x, y, t))
50
+ val cutoff = t - WINDOW_S
51
+ while (samples.size > 2 && samples[0].t < cutoff) samples.removeAt(0)
52
+ }
53
+
54
+ fun velocity(): Point {
55
+ if (samples.size < 2) return Point(0.0, 0.0)
56
+ val first = samples.first()
57
+ val last = samples.last()
58
+ val dt = last.t - first.t
59
+ if (dt <= 1e-6) return Point(0.0, 0.0)
60
+ return Point((last.x - first.x) / dt, (last.y - first.y) / dt)
61
+ }
62
+
63
+ fun reset() = samples.clear()
64
+
65
+ private companion object {
66
+ const val WINDOW_S = 0.1
67
+ }
68
+ }
69
+
70
+ internal fun centroid(pointers: Map<Int, Point>): Point {
71
+ if (pointers.isEmpty()) return Point(0.0, 0.0)
72
+ var xs = 0.0
73
+ var ys = 0.0
74
+ for (p in pointers.values) {
75
+ xs += p.x
76
+ ys += p.y
77
+ }
78
+ return Point(xs / pointers.size, ys / pointers.size)
79
+ }
80
+
81
+ /** Base class for one gesture's state machine. `pointers` maps pointer id to position. */
82
+ abstract class Recognizer(val index: Int, val config: GestureConfig, private val emitFn: EmitFn) {
83
+ protected fun emit(state: String, vararg fields: Pair<String, Any?>) {
84
+ val payload = LinkedHashMap<String, Any?>()
85
+ payload["kind"] = config.kind
86
+ payload["state"] = state
87
+ for ((k, v) in fields) payload[k] = v
88
+ emitFn(index, payload)
89
+ }
90
+
91
+ /** Report that this gesture can no longer succeed this interaction. */
92
+ protected fun fail() {
93
+ emitFn(index, mapOf("kind" to config.kind, "state" to GestureState.FAILED))
94
+ }
95
+
96
+ /** Abandon recognition without emitting anything (lost a race). */
97
+ open fun forceFail(t: Double) = cancel(t)
98
+
99
+ open fun down(pointers: Map<Int, Point>, t: Double) {}
100
+ open fun move(pointers: Map<Int, Point>, t: Double) {}
101
+ open fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {}
102
+ open fun cancel(t: Double) {}
103
+
104
+ /** Next time `poll` should run, or `null`. */
105
+ open fun deadline(): Double? = null
106
+ open fun poll(t: Double) {}
107
+
108
+ companion object {
109
+ /** Build the recognizer for `config.kind`, or `null` for unknown kinds. */
110
+ fun create(index: Int, config: GestureConfig, emit: EmitFn): Recognizer? = when (config.kind) {
111
+ "tap" -> TapRecognizer(index, config, emit)
112
+ "long_press" -> LongPressRecognizer(index, config, emit)
113
+ "pan" -> PanRecognizer(index, config, emit)
114
+ "swipe", "fling" -> SwipeRecognizer(index, config, emit)
115
+ "pinch" -> PinchRecognizer(index, config, emit)
116
+ "rotation" -> RotationRecognizer(index, config, emit)
117
+ else -> null
118
+ }
119
+ }
120
+ }
121
+
122
+ class TapRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
123
+ private val nTaps = max(1, config.nTaps)
124
+ private val slop = config.maxDistance
125
+ private var downPos: Point? = null
126
+ private var downTime = 0.0
127
+ private var tapCount = 0
128
+ private var lastTapTime = 0.0
129
+ private var failed = false
130
+ private var gapDeadline: Double? = null
131
+
132
+ override fun down(pointers: Map<Int, Point>, t: Double) {
133
+ if (pointers.size != 1) {
134
+ if (!failed) {
135
+ failed = true
136
+ fail()
137
+ }
138
+ return
139
+ }
140
+ if (tapCount > 0 && t - lastTapTime > MULTI_TAP_GAP_S) tapCount = 0
141
+ failed = false
142
+ gapDeadline = null
143
+ downPos = centroid(pointers)
144
+ downTime = t
145
+ }
146
+
147
+ override fun move(pointers: Map<Int, Point>, t: Double) {
148
+ val origin = downPos ?: return
149
+ if (failed) return
150
+ val c = centroid(pointers)
151
+ if (hypot(c.x - origin.x, c.y - origin.y) > slop) {
152
+ failed = true
153
+ fail()
154
+ }
155
+ }
156
+
157
+ override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
158
+ if (failed || downPos == null) {
159
+ reset()
160
+ return
161
+ }
162
+ if (t - downTime > MAX_TAP_DURATION_S) {
163
+ reset()
164
+ fail()
165
+ return
166
+ }
167
+ tapCount += 1
168
+ lastTapTime = t
169
+ if (tapCount >= nTaps) {
170
+ emit(GestureState.ENDED, "x" to x, "y" to y)
171
+ reset()
172
+ } else {
173
+ gapDeadline = t + MULTI_TAP_GAP_S
174
+ }
175
+ downPos = null
176
+ }
177
+
178
+ override fun cancel(t: Double) = reset()
179
+
180
+ override fun deadline(): Double? = gapDeadline
181
+
182
+ override fun poll(t: Double) {
183
+ val d = gapDeadline ?: return
184
+ if (t >= d) {
185
+ gapDeadline = null
186
+ tapCount = 0
187
+ fail()
188
+ }
189
+ }
190
+
191
+ private fun reset() {
192
+ downPos = null
193
+ if (tapCount >= nTaps) tapCount = 0
194
+ failed = false
195
+ gapDeadline = null
196
+ }
197
+
198
+ private companion object {
199
+ const val MAX_TAP_DURATION_S = 0.4
200
+ const val MULTI_TAP_GAP_S = 0.3
201
+ }
202
+ }
203
+
204
+ class LongPressRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
205
+ private val durationS = config.minDurationMs / 1000.0
206
+ private val slop = config.maxDistance
207
+ private var downPos: Point? = null
208
+ private var pressDeadline: Double? = null
209
+ private var active = false
210
+
211
+ override fun down(pointers: Map<Int, Point>, t: Double) {
212
+ downPos = centroid(pointers)
213
+ pressDeadline = t + durationS
214
+ active = false
215
+ }
216
+
217
+ override fun move(pointers: Map<Int, Point>, t: Double) {
218
+ val origin = downPos ?: return
219
+ val c = centroid(pointers)
220
+ if (hypot(c.x - origin.x, c.y - origin.y) > slop) {
221
+ if (active) emit(GestureState.CANCELLED, "x" to c.x, "y" to c.y)
222
+ reset()
223
+ fail()
224
+ }
225
+ }
226
+
227
+ override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
228
+ if (active) {
229
+ emit(GestureState.ENDED, "x" to x, "y" to y)
230
+ } else if (downPos != null) {
231
+ fail()
232
+ }
233
+ reset()
234
+ }
235
+
236
+ override fun cancel(t: Double) {
237
+ if (active) emit(GestureState.CANCELLED)
238
+ reset()
239
+ }
240
+
241
+ override fun deadline(): Double? = pressDeadline
242
+
243
+ override fun poll(t: Double) {
244
+ val d = pressDeadline ?: return
245
+ val origin = downPos ?: return
246
+ if (active) return
247
+ if (t >= d) {
248
+ active = true
249
+ pressDeadline = null
250
+ emit(GestureState.BEGAN, "x" to origin.x, "y" to origin.y)
251
+ }
252
+ }
253
+
254
+ private fun reset() {
255
+ downPos = null
256
+ pressDeadline = null
257
+ active = false
258
+ }
259
+ }
260
+
261
+ class PanRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
262
+ private val minDistance = config.minDistance
263
+ private val minPointers = max(1, config.minPointers)
264
+ private var origin: Point? = null
265
+ private var anchor: Point? = null
266
+ private val velocity = VelocityEstimator()
267
+ private var lastTranslation = Point(0.0, 0.0)
268
+
269
+ /** Whether the pan has activated (hosts use this to block parent interception). */
270
+ var active = false
271
+ private set
272
+
273
+ override fun down(pointers: Map<Int, Point>, t: Double) {
274
+ if (pointers.size < minPointers) return
275
+ if (origin == null) {
276
+ val c = centroid(pointers)
277
+ origin = c
278
+ velocity.reset()
279
+ velocity.add(c.x, c.y, t)
280
+ } else {
281
+ rebase(pointers)
282
+ }
283
+ }
284
+
285
+ override fun move(pointers: Map<Int, Point>, t: Double) {
286
+ val o = origin ?: return
287
+ if (pointers.size < minPointers) return
288
+ val c = centroid(pointers)
289
+ velocity.add(c.x, c.y, t)
290
+ if (!active) {
291
+ if (hypot(c.x - o.x, c.y - o.y) < minDistance) return
292
+ active = true
293
+ anchor = c
294
+ emit(GestureState.BEGAN, "x" to c.x, "y" to c.y, "pointer_count" to pointers.size)
295
+ return
296
+ }
297
+ val a = anchor ?: return
298
+ val v = velocity.velocity()
299
+ lastTranslation = Point(c.x - a.x, c.y - a.y)
300
+ emit(
301
+ GestureState.CHANGED,
302
+ "x" to c.x,
303
+ "y" to c.y,
304
+ "translation_x" to lastTranslation.x,
305
+ "translation_y" to lastTranslation.y,
306
+ "velocity_x" to v.x,
307
+ "velocity_y" to v.y,
308
+ "pointer_count" to pointers.size,
309
+ )
310
+ }
311
+
312
+ override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
313
+ if (active && pointers.size < minPointers) {
314
+ val v = velocity.velocity()
315
+ val a = anchor ?: Point(x, y)
316
+ emit(
317
+ GestureState.ENDED,
318
+ "x" to x,
319
+ "y" to y,
320
+ "translation_x" to x - a.x,
321
+ "translation_y" to y - a.y,
322
+ "velocity_x" to v.x,
323
+ "velocity_y" to v.y,
324
+ "pointer_count" to pointers.size,
325
+ )
326
+ reset()
327
+ } else if (pointers.isEmpty()) {
328
+ if (!active && origin != null) fail()
329
+ reset()
330
+ } else if (active) {
331
+ rebase(pointers)
332
+ }
333
+ }
334
+
335
+ override fun cancel(t: Double) {
336
+ if (active) emit(GestureState.CANCELLED)
337
+ reset()
338
+ }
339
+
340
+ private fun rebase(pointers: Map<Int, Point>) {
341
+ val a = anchor
342
+ if (!active || a == null) {
343
+ origin = centroid(pointers)
344
+ return
345
+ }
346
+ val c = centroid(pointers)
347
+ anchor = Point(c.x - lastTranslation.x, c.y - lastTranslation.y)
348
+ }
349
+
350
+ private fun reset() {
351
+ origin = null
352
+ anchor = null
353
+ active = false
354
+ velocity.reset()
355
+ lastTranslation = Point(0.0, 0.0)
356
+ }
357
+ }
358
+
359
+ /** Directional flick recognizer; also serves `fling` (adds a pointer-count requirement). */
360
+ class SwipeRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
361
+ private val direction = config.direction
362
+ private val minVelocity = config.minVelocity
363
+ private val nPointers = max(1, config.nPointers)
364
+ private val velocity = VelocityEstimator()
365
+ private var tracking = false
366
+ private var maxPointers = 0
367
+
368
+ override fun down(pointers: Map<Int, Point>, t: Double) {
369
+ if (!tracking) {
370
+ velocity.reset()
371
+ tracking = true
372
+ maxPointers = 0
373
+ }
374
+ maxPointers = max(maxPointers, pointers.size)
375
+ val c = centroid(pointers)
376
+ velocity.add(c.x, c.y, t)
377
+ }
378
+
379
+ override fun move(pointers: Map<Int, Point>, t: Double) {
380
+ if (!tracking) return
381
+ maxPointers = max(maxPointers, pointers.size)
382
+ val c = centroid(pointers)
383
+ velocity.add(c.x, c.y, t)
384
+ }
385
+
386
+ override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
387
+ if (!tracking || pointers.isNotEmpty()) return
388
+ tracking = false
389
+ velocity.add(x, y, t)
390
+ val v = velocity.velocity()
391
+ val speed = hypot(v.x, v.y)
392
+ if (speed < minVelocity || maxPointers < nPointers) {
393
+ fail()
394
+ return
395
+ }
396
+ val resolved = if (abs(v.x) >= abs(v.y)) {
397
+ if (v.x > 0) "right" else "left"
398
+ } else {
399
+ if (v.y > 0) "down" else "up"
400
+ }
401
+ if (direction != "any" && direction != resolved) {
402
+ fail()
403
+ return
404
+ }
405
+ emit(
406
+ GestureState.ENDED,
407
+ "x" to x,
408
+ "y" to y,
409
+ "velocity_x" to v.x,
410
+ "velocity_y" to v.y,
411
+ "direction" to resolved,
412
+ "pointer_count" to maxPointers,
413
+ )
414
+ }
415
+
416
+ override fun cancel(t: Double) {
417
+ tracking = false
418
+ maxPointers = 0
419
+ velocity.reset()
420
+ }
421
+ }
422
+
423
+ class PinchRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
424
+ private var initial: Double? = null
425
+ private var active = false
426
+ private var scale = 1.0
427
+
428
+ private fun span(pointers: Map<Int, Point>): Double? {
429
+ if (pointers.size < 2) return null
430
+ val pts = pointers.values.take(2)
431
+ return hypot(pts[1].x - pts[0].x, pts[1].y - pts[0].y)
432
+ }
433
+
434
+ override fun down(pointers: Map<Int, Point>, t: Double) {
435
+ val s = span(pointers)
436
+ if (s != null && s > 0 && initial == null) {
437
+ initial = s
438
+ active = true
439
+ val c = centroid(pointers)
440
+ emit(GestureState.BEGAN, "x" to c.x, "y" to c.y, "scale" to 1.0, "pointer_count" to pointers.size)
441
+ }
442
+ }
443
+
444
+ override fun move(pointers: Map<Int, Point>, t: Double) {
445
+ val i = initial ?: return
446
+ if (!active) return
447
+ val s = span(pointers) ?: return
448
+ if (s <= 0) return
449
+ scale = s / i
450
+ val c = centroid(pointers)
451
+ emit(GestureState.CHANGED, "x" to c.x, "y" to c.y, "scale" to scale, "pointer_count" to pointers.size)
452
+ }
453
+
454
+ override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
455
+ if (active && pointers.size < 2) {
456
+ emit(GestureState.ENDED, "x" to x, "y" to y, "scale" to scale, "pointer_count" to pointers.size)
457
+ reset()
458
+ } else if (!active && pointers.isEmpty()) {
459
+ fail()
460
+ }
461
+ }
462
+
463
+ override fun cancel(t: Double) {
464
+ if (active) emit(GestureState.CANCELLED, "scale" to scale)
465
+ reset()
466
+ }
467
+
468
+ private fun reset() {
469
+ initial = null
470
+ active = false
471
+ scale = 1.0
472
+ }
473
+ }
474
+
475
+ class RotationRecognizer(index: Int, config: GestureConfig, emit: EmitFn) : Recognizer(index, config, emit) {
476
+ private var initial: Double? = null
477
+ private var active = false
478
+ private var rotation = 0.0
479
+
480
+ private fun angle(pointers: Map<Int, Point>): Double? {
481
+ if (pointers.size < 2) return null
482
+ val pts = pointers.values.take(2)
483
+ return atan2(pts[1].y - pts[0].y, pts[1].x - pts[0].x)
484
+ }
485
+
486
+ override fun down(pointers: Map<Int, Point>, t: Double) {
487
+ val a = angle(pointers)
488
+ if (a != null && initial == null) {
489
+ initial = a
490
+ active = true
491
+ val c = centroid(pointers)
492
+ emit(GestureState.BEGAN, "x" to c.x, "y" to c.y, "rotation" to 0.0, "pointer_count" to pointers.size)
493
+ }
494
+ }
495
+
496
+ override fun move(pointers: Map<Int, Point>, t: Double) {
497
+ val i = initial ?: return
498
+ if (!active) return
499
+ val a = angle(pointers) ?: return
500
+ var delta = a - i
501
+ while (delta > Math.PI) delta -= 2 * Math.PI
502
+ while (delta < -Math.PI) delta += 2 * Math.PI
503
+ rotation = delta
504
+ val c = centroid(pointers)
505
+ emit(GestureState.CHANGED, "x" to c.x, "y" to c.y, "rotation" to rotation, "pointer_count" to pointers.size)
506
+ }
507
+
508
+ override fun up(pointers: Map<Int, Point>, t: Double, x: Double, y: Double) {
509
+ if (active && pointers.size < 2) {
510
+ emit(GestureState.ENDED, "x" to x, "y" to y, "rotation" to rotation, "pointer_count" to pointers.size)
511
+ reset()
512
+ } else if (!active && pointers.isEmpty()) {
513
+ fail()
514
+ }
515
+ }
516
+
517
+ override fun cancel(t: Double) {
518
+ if (active) emit(GestureState.CANCELLED, "rotation" to rotation)
519
+ reset()
520
+ }
521
+
522
+ private fun reset() {
523
+ initial = null
524
+ active = false
525
+ rotation = 0.0
526
+ }
527
+ }
@@ -0,0 +1,145 @@
1
+ package com.pythonnative.runtime.layout
2
+
3
+ import com.pythonnative.runtime.PNBridge
4
+ import com.pythonnative.runtime.bridge.Op
5
+ import org.json.JSONArray
6
+ import org.json.JSONObject
7
+
8
+ /** Native layout and measurement, with one result containing changed geometry. */
9
+ object NativeLayout {
10
+ private class Entry(val yoga: YogaNode) {
11
+ val props = JSONObject()
12
+ val children = ArrayList<Long>()
13
+ var parent: Long? = null
14
+ var attached = false
15
+ var frame = floatArrayOf()
16
+ }
17
+ private val nodes = HashMap<Long, Entry>()
18
+ private var viewport = JSONObject()
19
+ private val detached = setOf("VirtualList", "Modal", "ScreenStack")
20
+ private val containers = detached + setOf("View", "Row", "Column", "ScrollView", "Screen", "Portal")
21
+ private var scheduled = false
22
+
23
+ fun containerDidLayout() {
24
+ if (scheduled) return
25
+ scheduled = true
26
+ android.os.Handler(android.os.Looper.getMainLooper()).post {
27
+ scheduled = false
28
+ val frames = compute(viewport)
29
+ if (frames.length() > 0) PNBridge.callPython("layout", 0, "", frames.toString())
30
+ }
31
+ }
32
+
33
+ fun reset() {
34
+ for (entry in nodes.values) if (entry.attached) entry.parent?.let { parent ->
35
+ nodes[parent]?.yoga?.let { it.remove(it.ptr, entry.yoga.ptr) }
36
+ }
37
+ for (entry in nodes.values) entry.yoga.close()
38
+ nodes.clear()
39
+ viewport = JSONObject()
40
+ }
41
+
42
+ fun parent(tag: Long): Long? = nodes[tag]?.parent
43
+
44
+ fun observe(ops: List<Op>) {
45
+ for (op in ops) when (op) {
46
+ is Op.Create -> {
47
+ val entry = Entry(YogaNode(op.tag))
48
+ nodes[op.tag] = entry
49
+ update(entry, op.props)
50
+ }
51
+ is Op.Update -> nodes[op.tag]?.let { update(it, op.changed) }
52
+ is Op.Insert -> {
53
+ val parent = nodes[op.parent] ?: continue
54
+ val child = nodes[op.child] ?: continue
55
+ child.parent?.let { old -> nodes[old]?.let { previous ->
56
+ previous.children.remove(op.child)
57
+ if (child.attached) previous.yoga.remove(previous.yoga.ptr, child.yoga.ptr)
58
+ } }
59
+ child.parent = op.parent
60
+ parent.children.add(op.index.coerceAtMost(parent.children.size), op.child)
61
+ child.attached = PNBridge.registry.get(op.parent)?.typeName !in detached
62
+ if (child.attached) parent.yoga.insert(parent.yoga.ptr, child.yoga.ptr, op.index)
63
+ }
64
+ is Op.Destroy -> nodes.remove(op.tag)?.let { child ->
65
+ child.parent?.let { old -> nodes[old]?.let { parent ->
66
+ parent.children.remove(op.tag)
67
+ if (child.attached) parent.yoga.remove(parent.yoga.ptr, child.yoga.ptr)
68
+ } }
69
+ child.yoga.close()
70
+ }
71
+ is Op.Frame -> Unit
72
+ }
73
+ }
74
+
75
+ private fun update(entry: Entry, changed: JSONObject) {
76
+ for (key in changed.keys()) {
77
+ if (changed.isNull(key)) entry.props.remove(key) else entry.props.put(key, changed.get(key))
78
+ }
79
+ val yoga = entry.yoga
80
+ yoga.resetStyle(yoga.ptr)
81
+ for (key in entry.props.keys()) {
82
+ val value = entry.props.get(key)
83
+ if (value is JSONObject && key in setOf("margin", "padding")) {
84
+ for (edge in value.keys()) yoga.style(yoga.ptr, if (edge == "all") key else "${key}_$edge", value.get(edge).toString())
85
+ } else yoga.style(yoga.ptr, key, value.toString())
86
+ }
87
+ val type = PNBridge.registry.get(yoga.tag)?.typeName
88
+ if (type in setOf("ScrollView", "VirtualList", "ScreenStack")) yoga.style(yoga.ptr, "flex_shrink", "1")
89
+ yoga.measureLeaf(yoga.ptr, entry.children.isEmpty() && type !in containers)
90
+ }
91
+
92
+ fun compute(request: JSONObject): JSONArray {
93
+ viewport = request
94
+ val width = request.optDouble("width").toFloat()
95
+ val height = request.optDouble("height").toFloat()
96
+ if (!width.isFinite() || !height.isFinite() || width <= 0 || height <= 0) return JSONArray()
97
+ val roots = request.optJSONArray("roots") ?: JSONArray()
98
+ val rootTags = (0 until roots.length()).map { roots.getLong(it) }.toSet()
99
+ for (tag in rootTags) nodes[tag]?.yoga?.let { it.calculate(it.ptr, width, height) }
100
+ // Portals have no on-screen parent. Their own Yoga node supplies the
101
+ // viewport for all children, including absolute insets and sibling layout.
102
+ for ((tag, entry) in nodes) {
103
+ val record = PNBridge.registry.get(tag) ?: continue
104
+ if (record.typeName != "Portal") continue
105
+ val containerWidth = record.view.width / PNBridge.density()
106
+ val containerHeight = record.view.height / PNBridge.density()
107
+ val portalWidth = if (containerWidth > 0) containerWidth else width
108
+ val portalHeight = if (containerHeight > 0) containerHeight else height
109
+ entry.yoga.style(entry.yoga.ptr, "width", portalWidth.toString())
110
+ entry.yoga.style(entry.yoga.ptr, "height", portalHeight.toString())
111
+ entry.yoga.calculate(entry.yoga.ptr, portalWidth, portalHeight)
112
+ }
113
+ for (entry in nodes.values) if (entry.parent != null && !entry.attached) {
114
+ val parent = PNBridge.registry.get(entry.parent!!)
115
+ val record = PNBridge.registry.get(entry.yoga.tag)
116
+ val container = if (record?.typeName == "Screen") record.view else parent?.view
117
+ val availableWidth = (container?.width ?: 0) / PNBridge.density()
118
+ val availableHeight = (container?.height ?: 0) / PNBridge.density()
119
+ val isList = parent?.typeName == "VirtualList"
120
+ val horizontal = parent?.props?.optBoolean("horizontal", false) ?: false
121
+ entry.yoga.calculate(entry.yoga.ptr, if (isList && horizontal) Float.NaN else if (availableWidth > 0) availableWidth else width,
122
+ if (isList && !horizontal) Float.NaN else if (availableHeight > 0) availableHeight else height)
123
+ }
124
+ val frames = JSONArray()
125
+ for ((tag, entry) in nodes) {
126
+ val frame = entry.yoga.frame(entry.yoga.ptr)
127
+ if (frame.contentEquals(entry.frame)) continue
128
+ entry.frame = frame
129
+ if (tag !in rootTags) PNBridge.registry.get(tag)?.let { record ->
130
+ record.frame = frame.map { it.toDouble() }.toDoubleArray()
131
+ record.manager.setFrame(record.view, frame[0].toDouble(), frame[1].toDouble(), frame[2].toDouble(), frame[3].toDouble())
132
+ }
133
+ com.pythonnative.runtime.components.VirtualListManager.measured(tag, frame[2].toDouble(), frame[3].toDouble())
134
+ frames.put(JSONArray().put(tag).put(frame[0]).put(frame[1]).put(frame[2]).put(frame[3]))
135
+ }
136
+ return frames
137
+ }
138
+
139
+ fun invalidate(tag: Long) {
140
+ val entry = nodes[tag] ?: return
141
+ if (entry.children.isNotEmpty()) return
142
+ entry.yoga.measureLeaf(entry.yoga.ptr, true)
143
+ PNBridge.callPython("layout", 0, "", compute(viewport).toString())
144
+ }
145
+ }
@@ -0,0 +1,29 @@
1
+ package com.pythonnative.runtime.layout
2
+
3
+ import android.widget.TextView
4
+ import com.pythonnative.runtime.PNBridge
5
+
6
+ /** Explicit ownership of a node in the pinned, shared Yoga core. */
7
+ class YogaNode(val tag: Long) : AutoCloseable {
8
+ companion object { init { System.loadLibrary("pn_yoga") } }
9
+ val ptr = create()
10
+ private var closed = false
11
+ private external fun create(): Long
12
+ private external fun free(ptr: Long)
13
+ external fun style(ptr: Long, key: String, value: String)
14
+ external fun resetStyle(ptr: Long)
15
+ external fun measureLeaf(ptr: Long, enabled: Boolean)
16
+ external fun insert(ptr: Long, child: Long, index: Int)
17
+ external fun remove(ptr: Long, child: Long)
18
+ external fun calculate(ptr: Long, width: Float, height: Float)
19
+ external fun frame(ptr: Long): FloatArray
20
+ fun measure(width: Float, height: Float): FloatArray {
21
+ val record = PNBridge.registry.get(tag) ?: return floatArrayOf(0f, 0f)
22
+ return record.manager.measure(record.view, width.toDouble(), height.toDouble())
23
+ }
24
+ fun baseline(height: Float): Float {
25
+ val view = PNBridge.registry.get(tag)?.view as? TextView ?: return height
26
+ return -view.paint.fontMetrics.ascent / PNBridge.density()
27
+ }
28
+ override fun close() { if (!closed) { closed = true; free(ptr) } }
29
+ }