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,188 @@
1
+ package com.pythonnative.runtime.screens
2
+
3
+ import android.os.Bundle
4
+ import android.view.LayoutInflater
5
+ import android.view.View
6
+ import android.view.ViewGroup
7
+ import android.widget.FrameLayout
8
+ import androidx.activity.OnBackPressedCallback
9
+ import androidx.core.os.bundleOf
10
+ import androidx.core.view.ViewCompat
11
+ import androidx.fragment.app.Fragment
12
+ import com.pythonnative.runtime.PNBridge
13
+ import com.pythonnative.runtime.bridge.PNLog
14
+ import org.json.JSONObject
15
+
16
+ /**
17
+ * The Fragment hosting one PythonNative screen.
18
+ *
19
+ * On view creation it asks Python to create the screen
20
+ * (`callback("host", screenId, "create", {...})`) and afterwards
21
+ * forwards lifecycle and layout: `start`, `layout`, `resume`, `pause`,
22
+ * `stop`, `destroy`, `back_pressed`, `save_state`, and
23
+ * `restore_state`. Python attaches the screen's root view through the
24
+ * `Host.attach_root` module call, which lands in [attachRoot].
25
+ *
26
+ * Apps subclass this (the nav graph names the subclass) and override
27
+ * [defaultPath] to supply the entry module when the fragment arguments
28
+ * don't carry one. Fast Refresh needs nothing from the fragment: the
29
+ * Python dev client reloads modules and refreshes mounted screens.
30
+ */
31
+ open class PNScreenFragment : Fragment() {
32
+ /** The screen id assigned by [ScreenRegistry]. */
33
+ var screenId: Int = 0
34
+ private set
35
+
36
+ /** The container the root view is attached into (valid between `onCreateView` and `onDestroyView`). */
37
+ var container: FrameLayout? = null
38
+ private set
39
+
40
+ private var created = false
41
+ private var pendingRestore: String? = null
42
+ private var lastLayout: String? = null
43
+
44
+ /** Screen path when the arguments carry none (apps return the entry module). */
45
+ protected open fun defaultPath(): String? = null
46
+
47
+ /** The path this fragment shows. */
48
+ fun screenPath(): String? = arguments?.getString(ARG_PATH) ?: defaultPath()
49
+
50
+ private fun argsJson(): String? = arguments?.getString(ARG_ARGS)
51
+
52
+ override fun onCreate(savedInstanceState: Bundle?) {
53
+ super.onCreate(savedInstanceState)
54
+ screenId = ScreenRegistry.register(this)
55
+ pendingRestore = savedInstanceState?.getString(STATE_KEY)
56
+ requireActivity().onBackPressedDispatcher.addCallback(
57
+ this,
58
+ object : OnBackPressedCallback(true) {
59
+ override fun handleOnBackPressed() {
60
+ if (created) host("back_pressed", "{}")
61
+ else requireActivity().finish()
62
+
63
+ }
64
+ },
65
+ )
66
+ }
67
+
68
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
69
+ val frame = FrameLayout(requireContext())
70
+ frame.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
71
+ this.container = frame
72
+ return frame
73
+ }
74
+
75
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
76
+ super.onViewCreated(view, savedInstanceState)
77
+ arguments?.getString(ARG_TITLE)?.let { activity?.title = it }
78
+ val payload = JSONObject()
79
+ .put("path", screenPath() ?: JSONObject.NULL)
80
+ .put("args", argsJson() ?: JSONObject.NULL)
81
+ host("create", payload.toString())
82
+ created = true
83
+ pendingRestore?.let {
84
+ host("restore_state", JSONObject().put("state", it).toString())
85
+ pendingRestore = null
86
+ }
87
+ view.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ -> publishLayout(v) }
88
+ ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
89
+ publishLayout(v, force = true)
90
+ insets
91
+ }
92
+ publishLayout(view, force = true)
93
+ }
94
+
95
+ private fun publishLayout(view: View, force: Boolean = false) {
96
+ if (!created) return
97
+ val payload = Viewport.describe(view).toString()
98
+ if (!force && payload == lastLayout) return
99
+ lastLayout = payload
100
+ host("layout", payload)
101
+ }
102
+
103
+ /** Current viewport payload for this screen. */
104
+ fun viewport(): JSONObject {
105
+ val v = container ?: view
106
+ return if (v != null) Viewport.describe(v) else JSONObject()
107
+ }
108
+
109
+ /** Attach `root` (MATCH_PARENT) into the fragment container, replacing any previous root. */
110
+ fun attachRoot(root: View) {
111
+ val target = container ?: return
112
+ target.removeAllViews()
113
+ (root.parent as? ViewGroup)?.removeView(root)
114
+ target.addView(root, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
115
+ publishLayout(target, force = true)
116
+ }
117
+
118
+ /** Detach `root` from wherever it is parented (never clears the shared container). */
119
+ fun detachRoot(root: View) {
120
+ (root.parent as? ViewGroup)?.removeView(root)
121
+ }
122
+
123
+ override fun onStart() {
124
+ super.onStart()
125
+ host("start", "{}")
126
+ }
127
+
128
+ override fun onResume() {
129
+ super.onResume()
130
+ ScreenRegistry.setActive(screenId)
131
+ host("resume", viewport().toString())
132
+ }
133
+
134
+ override fun onPause() {
135
+ super.onPause()
136
+ host("pause", "{}")
137
+ }
138
+
139
+ override fun onStop() {
140
+ super.onStop()
141
+ host("stop", "{}")
142
+ }
143
+
144
+ var cachedStateJSON: String? = null
145
+
146
+ override fun onSaveInstanceState(outState: Bundle) {
147
+ super.onSaveInstanceState(outState)
148
+ if (!created) return
149
+ host("save_state", "{}")
150
+ cachedStateJSON?.let { outState.putString(STATE_KEY, it) }
151
+ }
152
+
153
+ override fun onDestroyView() {
154
+ super.onDestroyView()
155
+ container = null
156
+ }
157
+
158
+ override fun onDestroy() {
159
+ super.onDestroy()
160
+ if (created) host("destroy", "{}")
161
+ created = false
162
+ ScreenRegistry.unregister(screenId)
163
+ }
164
+
165
+ private fun host(name: String, payloadJson: String): String? {
166
+ return try {
167
+ PNBridge.callPython("host", screenId.toLong(), name, payloadJson)
168
+ } catch (e: Exception) {
169
+ PNLog.rateLimited("host:$name", "host callback '$name' failed", e)
170
+ null
171
+ }
172
+ }
173
+
174
+ companion object {
175
+ const val ARG_PATH = "screen_path"
176
+ const val ARG_ARGS = "args_json"
177
+ const val ARG_TITLE = "title"
178
+ private const val STATE_KEY = "pn_screen_state"
179
+
180
+ /** Build a fragment for `path` with optional JSON `args`. */
181
+ @JvmStatic
182
+ fun newInstance(path: String, argsJson: String?): PNScreenFragment {
183
+ val f = PNScreenFragment()
184
+ f.arguments = bundleOf(ARG_PATH to path, ARG_ARGS to argsJson)
185
+ return f
186
+ }
187
+ }
188
+ }
@@ -0,0 +1,80 @@
1
+ package com.pythonnative.runtime.screens
2
+
3
+ import android.content.res.Configuration
4
+ import android.view.View
5
+ import android.view.ViewGroup
6
+ import androidx.core.view.ViewCompat
7
+ import androidx.core.view.WindowInsetsCompat
8
+ import com.pythonnative.runtime.PNBridge
9
+ import org.json.JSONObject
10
+ import kotlin.math.max
11
+
12
+ /**
13
+ * Integer ids for live [PNScreenFragment]s. Python addresses screens
14
+ * by these ids in `Host` module calls and receives them as the `tag`
15
+ * of `host` callbacks.
16
+ */
17
+ object ScreenRegistry {
18
+ private val screens = LinkedHashMap<Int, PNScreenFragment>()
19
+ private var nextId = 1
20
+ private var activeId = 0
21
+
22
+ /** Assign an id to `fragment`. */
23
+ fun register(fragment: PNScreenFragment): Int {
24
+ val id = nextId++
25
+ screens[id] = fragment
26
+ return id
27
+ }
28
+
29
+ fun unregister(id: Int) {
30
+ screens.remove(id)
31
+ if (activeId == id) activeId = screens.keys.lastOrNull() ?: 0
32
+ }
33
+
34
+ fun get(id: Int): PNScreenFragment? = screens[id]
35
+
36
+ /** Mark `id` as the screen the user currently sees (called on resume). */
37
+ fun setActive(id: Int) {
38
+ activeId = id
39
+ }
40
+
41
+ /** The visible screen's id, or `0`. */
42
+ fun activeId(): Int = activeId
43
+
44
+ /** The fragment container of the visible screen (overlay host for `Portal`). */
45
+ fun activeContainer(): ViewGroup? = screens[activeId]?.container ?: screens.values.lastOrNull()?.container
46
+ }
47
+
48
+ /** Builds the viewport payload shared by `layout`, `resume`, and `Host.viewport`. */
49
+ object Viewport {
50
+ /**
51
+ * `{width, height, insets{top,left,bottom,right}, color_scheme, keyboard_height}`
52
+ * in dp, measured from `view` (falling back to display metrics when
53
+ * the view has not been laid out yet).
54
+ */
55
+ fun describe(view: View): JSONObject {
56
+ val density = PNBridge.density()
57
+ val metrics = view.resources.displayMetrics
58
+ val w = if (view.width > 0) view.width else metrics.widthPixels
59
+ val h = if (view.height > 0) view.height else metrics.heightPixels
60
+ val insets = ViewCompat.getRootWindowInsets(view)
61
+ val bars = insets?.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
62
+ val ime = insets?.getInsets(WindowInsetsCompat.Type.ime())
63
+ val bottomBar = bars?.bottom ?: 0
64
+ val keyboard = max(0, (ime?.bottom ?: 0) - bottomBar) / density
65
+ val night = view.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
66
+ return JSONObject()
67
+ .put("width", w / density.toDouble())
68
+ .put("height", h / density.toDouble())
69
+ .put(
70
+ "insets",
71
+ JSONObject()
72
+ .put("top", (bars?.top ?: 0) / density.toDouble())
73
+ .put("left", (bars?.left ?: 0) / density.toDouble())
74
+ .put("bottom", bottomBar / density.toDouble())
75
+ .put("right", (bars?.right ?: 0) / density.toDouble()),
76
+ )
77
+ .put("color_scheme", if (night == Configuration.UI_MODE_NIGHT_YES) "dark" else "light")
78
+ .put("keyboard_height", keyboard.toDouble())
79
+ }
80
+ }
@@ -0,0 +1,48 @@
1
+ package com.pythonnative.runtime.views
2
+
3
+ import android.os.Build
4
+ import android.view.View
5
+ import android.view.accessibility.AccessibilityNodeInfo
6
+ import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
7
+
8
+ /**
9
+ * Accessibility delegate that exposes PythonNative's `test_id` and
10
+ * `accessibility_state` props through the Android accessibility tree.
11
+ *
12
+ * `test_id` is surfaced as the node's view-id resource name, which
13
+ * UI Automator-based tools (Maestro, UiAutomator2, Appium) match as
14
+ * `resource-id`. State flags map onto the closest
15
+ * [AccessibilityNodeInfo] equivalents so TalkBack announces them.
16
+ * Fields left null are not applied.
17
+ */
18
+ class PNAccessibilityDelegate : View.AccessibilityDelegate() {
19
+ var testId: String? = null
20
+ var stateDisabled: Boolean? = null
21
+ var stateSelected: Boolean? = null
22
+ var stateChecked: Boolean? = null
23
+ var stateBusy: Boolean? = null
24
+ var stateExpanded: Boolean? = null
25
+ var role: String? = null
26
+
27
+ override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) {
28
+ super.onInitializeAccessibilityNodeInfo(host, info)
29
+ testId?.let { info.viewIdResourceName = it }
30
+ stateDisabled?.let { info.isEnabled = !it }
31
+ stateSelected?.let { info.isSelected = it }
32
+ stateChecked?.let {
33
+ info.isCheckable = true
34
+ info.isChecked = it
35
+ }
36
+ role?.let { AccessibilityNodeInfoCompat.wrap(info).roleDescription = it }
37
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
38
+ val states = mutableListOf<String>()
39
+ if (stateBusy == true) states.add("busy")
40
+ when (stateExpanded) {
41
+ true -> states.add("expanded")
42
+ false -> states.add("collapsed")
43
+ null -> {}
44
+ }
45
+ if (states.isNotEmpty()) info.stateDescription = states.joinToString(", ")
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,76 @@
1
+ package com.pythonnative.runtime.views
2
+
3
+ import android.graphics.Canvas
4
+ import android.graphics.ColorFilter
5
+ import android.graphics.Paint
6
+ import android.graphics.PixelFormat
7
+ import android.graphics.RectF
8
+ import android.graphics.drawable.Drawable
9
+
10
+ /**
11
+ * Background drawable that renders an optional rounded fill plus four
12
+ * independent border strips. Used for PythonNative's
13
+ * `border_<side>_width` / `border_<side>_color` style props, which
14
+ * `GradientDrawable`'s single uniform stroke cannot express.
15
+ *
16
+ * Widths are in pixels; sides are ordered left, top, right, bottom.
17
+ * The fill color is mutable so animated `background_color` frames can
18
+ * update it in place without allocating a new drawable.
19
+ */
20
+ class PNBorderDrawable(
21
+ private var hasBackground: Boolean,
22
+ private var backgroundColor: Int,
23
+ private val cornerRadius: Float,
24
+ private val widths: FloatArray,
25
+ private val colors: IntArray,
26
+ ) : Drawable() {
27
+ private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
28
+
29
+ /** Replace the fill color (used by animated background frames). */
30
+ fun setFillColor(color: Int) {
31
+ hasBackground = true
32
+ backgroundColor = color
33
+ invalidateSelf()
34
+ }
35
+
36
+ override fun draw(canvas: Canvas) {
37
+ val b = RectF(bounds)
38
+ if (hasBackground) {
39
+ paint.style = Paint.Style.FILL
40
+ paint.color = backgroundColor
41
+ if (cornerRadius > 0f) {
42
+ canvas.drawRoundRect(b, cornerRadius, cornerRadius, paint)
43
+ } else {
44
+ canvas.drawRect(b, paint)
45
+ }
46
+ }
47
+ paint.style = Paint.Style.FILL
48
+ if (widths[0] > 0f) {
49
+ paint.color = colors[0]
50
+ canvas.drawRect(b.left, b.top, b.left + widths[0], b.bottom, paint)
51
+ }
52
+ if (widths[1] > 0f) {
53
+ paint.color = colors[1]
54
+ canvas.drawRect(b.left, b.top, b.right, b.top + widths[1], paint)
55
+ }
56
+ if (widths[2] > 0f) {
57
+ paint.color = colors[2]
58
+ canvas.drawRect(b.right - widths[2], b.top, b.right, b.bottom, paint)
59
+ }
60
+ if (widths[3] > 0f) {
61
+ paint.color = colors[3]
62
+ canvas.drawRect(b.left, b.bottom - widths[3], b.right, b.bottom, paint)
63
+ }
64
+ }
65
+
66
+ override fun setAlpha(alpha: Int) {
67
+ paint.alpha = alpha
68
+ }
69
+
70
+ override fun setColorFilter(colorFilter: ColorFilter?) {
71
+ paint.colorFilter = colorFilter
72
+ }
73
+
74
+ @Deprecated("Deprecated in Java")
75
+ override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
76
+ }
@@ -0,0 +1,18 @@
1
+ package com.pythonnative.runtime.views
2
+
3
+ import android.content.Context
4
+ import androidx.appcompat.widget.AppCompatEditText
5
+
6
+ /**
7
+ * `EditText` that reports selection changes, which the platform only
8
+ * exposes through a protected override.
9
+ */
10
+ class PNEditText(context: Context) : AppCompatEditText(context) {
11
+ /** Called with `(start, end)` whenever the selection or cursor moves. */
12
+ var onSelectionChangedListener: ((Int, Int) -> Unit)? = null
13
+
14
+ override fun onSelectionChanged(selStart: Int, selEnd: Int) {
15
+ super.onSelectionChanged(selStart, selEnd)
16
+ onSelectionChangedListener?.invoke(selStart, selEnd)
17
+ }
18
+ }
@@ -0,0 +1,49 @@
1
+ package com.pythonnative.runtime.views
2
+
3
+ import android.content.Context
4
+ import android.view.MotionEvent
5
+ import android.widget.FrameLayout
6
+
7
+ /**
8
+ * Container `FrameLayout` with React Native-style `pointer_events`
9
+ * semantics. Component managers create these for flex containers and
10
+ * drive the mode via [setPointerEventsMode]:
11
+ *
12
+ * - `"auto"` (default): normal dispatch; the view and its children
13
+ * both receive touches.
14
+ * - `"none"`: neither the view nor its children receive touches; the
15
+ * event falls through to whatever sits underneath.
16
+ * - `"box_none"`: children receive touches, but the view itself never
17
+ * intercepts or consumes them (the styler also mutes the view's own
18
+ * touch listeners).
19
+ * - `"box_only"`: the view receives touches and its children don't;
20
+ * every event in the subtree is intercepted at this level.
21
+ */
22
+ open class PNFrameLayout(context: Context) : FrameLayout(context) {
23
+ private var pointerEventsMode: String = "auto"
24
+
25
+ /** Set the pointer-events mode; `null` restores `"auto"`. */
26
+ fun setPointerEventsMode(mode: String?) {
27
+ pointerEventsMode = mode ?: "auto"
28
+ }
29
+
30
+ /** The current pointer-events mode. */
31
+ fun getPointerEventsMode(): String = pointerEventsMode
32
+
33
+ override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
34
+ if (pointerEventsMode == "none") {
35
+ // Declining the whole dispatch lets the event pass through
36
+ // to views underneath, matching RN's "none".
37
+ return false
38
+ }
39
+ return super.dispatchTouchEvent(ev)
40
+ }
41
+
42
+ override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
43
+ return when (pointerEventsMode) {
44
+ "box_only" -> true
45
+ "box_none" -> false
46
+ else -> super.onInterceptTouchEvent(ev)
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,75 @@
1
+ package com.pythonnative.runtime
2
+
3
+ import com.pythonnative.runtime.animation.AnimationSpecs
4
+ import org.json.JSONArray
5
+ import org.json.JSONObject
6
+ import org.junit.Assert.assertArrayEquals
7
+ import org.junit.Assert.assertEquals
8
+ import org.junit.Assert.assertTrue
9
+ import org.junit.Test
10
+ import kotlin.math.exp
11
+ import kotlin.math.sqrt
12
+
13
+ class AnimationSpecsTest {
14
+ @Test
15
+ fun springDampingRatio() {
16
+ // Critically damped when damping = 2 * sqrt(k * m).
17
+ val k = 100.0
18
+ val m = 2.0
19
+ val critical = 2 * sqrt(k * m)
20
+ assertEquals(1.0, AnimationSpecs.dampingRatio(k, critical, m), 1e-9)
21
+ val spec = JSONObject("""{"kind":"spring","from":0,"to":1,"stiffness":100,"damping":10,"mass":1}""")
22
+ val spring = AnimationSpecs.spring(spec)
23
+ assertEquals(100.0, spring.stiffness, 1e-9)
24
+ assertEquals(0.5, spring.dampingRatio, 1e-9)
25
+ // Mass scales the effective stiffness so the natural frequency matches.
26
+ val heavy = AnimationSpecs.spring(JSONObject("""{"kind":"spring","stiffness":100,"damping":10,"mass":4}"""))
27
+ assertEquals(25.0, heavy.stiffness, 1e-9)
28
+ assertEquals(10.0 / (2 * sqrt(400.0)), heavy.dampingRatio, 1e-9)
29
+ }
30
+
31
+ @Test
32
+ fun decayFrictionReproducesPythonDecay() {
33
+ val k = 0.002
34
+ val friction = AnimationSpecs.decayFriction(k)
35
+ // FlingAnimation: v(t) = v0 * exp(-4.2 * friction * t); Python: v0 * exp(-k * 1000 * t).
36
+ val t = 0.25
37
+ assertEquals(exp(-k * 1000 * t), exp(-AnimationSpecs.FLING_FRICTION_SCALE * friction * t), 1e-9)
38
+ val decay = AnimationSpecs.decay(JSONObject("""{"kind":"decay","from":10,"velocity":2,"deceleration":0.002}"""))
39
+ assertEquals(2000.0, decay.startVelocity, 1e-9)
40
+ assertEquals(10.0 + 2.0 / (0.002 * 1000.0), decay.projectedFinal, 1e-9)
41
+ }
42
+
43
+ @Test
44
+ fun timingDefaults() {
45
+ val timing = AnimationSpecs.timing(JSONObject("""{"kind":"timing","from":0,"to":1}"""))
46
+ assertEquals(300L, timing.durationMs)
47
+ assertEquals(1.0, timing.to, 0.0)
48
+ }
49
+
50
+ @Test
51
+ fun easingNamesMatchPythonCurves() {
52
+ @Suppress("UNCHECKED_CAST")
53
+ val easeInOut = AnimationSpecs.resolveEasing("ease_in_out") as (Float) -> Float
54
+ assertEquals(0.5f, easeInOut(0.5f), 1e-6f)
55
+ assertEquals(0.15625f, easeInOut(0.25f), 1e-6f)
56
+ @Suppress("UNCHECKED_CAST")
57
+ val linear = AnimationSpecs.resolveEasing("linear") as (Float) -> Float
58
+ assertEquals(0.3f, linear(0.3f), 1e-6f)
59
+ @Suppress("UNCHECKED_CAST")
60
+ val fallback = AnimationSpecs.resolveEasing("does-not-exist") as (Float) -> Float
61
+ assertEquals(easeInOut(0.3f), fallback(0.3f), 1e-6f)
62
+ @Suppress("UNCHECKED_CAST")
63
+ val bounce = AnimationSpecs.resolveEasing("bounce") as (Float) -> Float
64
+ assertEquals(1f, bounce(1f), 1e-6f)
65
+ assertTrue(bounce(0.5f) in 0f..1f)
66
+ }
67
+
68
+ @Test
69
+ fun cubicBezierArraysAreControlPoints() {
70
+ val pts = AnimationSpecs.resolveEasing(JSONArray("[0.25, 0.1, 0.25, 1.0]")) as DoubleArray
71
+ assertArrayEquals(doubleArrayOf(0.25, 0.1, 0.25, 1.0), pts, 1e-9)
72
+ val css = AnimationSpecs.resolveEasing("cubic-bezier(0.42, 0, 1, 1)") as DoubleArray
73
+ assertArrayEquals(doubleArrayOf(0.42, 0.0, 1.0, 1.0), css, 1e-9)
74
+ }
75
+ }