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,134 @@
1
+ package com.pythonnative.runtime.components
2
+
3
+ import android.app.Dialog
4
+ import android.content.Context
5
+ import android.graphics.drawable.ColorDrawable
6
+ import android.view.View
7
+ import android.view.ViewGroup
8
+ import android.view.WindowManager
9
+ import android.widget.FrameLayout
10
+ import com.pythonnative.runtime.bridge.JsonUtil
11
+ import com.pythonnative.runtime.bridge.str
12
+ import com.pythonnative.runtime.bridge.value
13
+ import org.json.JSONObject
14
+
15
+ /**
16
+ * `Modal` element: real modal presentation backed by a `Dialog`.
17
+ *
18
+ * The on-tree placeholder is a hidden `View`. When `visible` flips to
19
+ * `true`, a `Dialog` hosting a `FrameLayout` is shown and the
20
+ * reconciler's child inserts are forwarded into that content view.
21
+ */
22
+ class ModalManager : ComponentManager() {
23
+ override fun createView(context: Context, tag: Long, props: JSONObject): View {
24
+ val placeholder = View(context)
25
+ placeholder.visibility = View.GONE
26
+ return placeholder
27
+ }
28
+
29
+ override fun applyProps(view: View, props: JSONObject, initial: Boolean) {
30
+ val state = stateOf(view)
31
+ // Only react when `visible` itself changed; a re-render while the
32
+ // dialog is open must not tear it down.
33
+ if (props.has("visible")) {
34
+ val visible = JsonUtil.truthy(props.value("visible"))
35
+ if (visible && state["dialog"] == null) present(view)
36
+ else if (!visible && state["dialog"] != null) dismiss(view, fromUser = false)
37
+ }
38
+ val dialog = state["dialog"] as? Dialog
39
+ if (dialog != null && props.has("dismiss_on_backdrop")) {
40
+ dialog.setCanceledOnTouchOutside(props.value("dismiss_on_backdrop") != false)
41
+ }
42
+ }
43
+
44
+ override fun insertChild(parent: View, child: View, index: Int) {
45
+ val state = stateOf(parent)
46
+ val content = state["content_view"] as? FrameLayout
47
+ if (content != null) {
48
+ ViewChildren.insert(content, child, index)
49
+ } else {
50
+ @Suppress("UNCHECKED_CAST")
51
+ val pending = state.getOrPut("pending") { ArrayList<View>() } as ArrayList<View>
52
+ pending.remove(child)
53
+ pending.add(index.coerceIn(0, pending.size), child)
54
+ }
55
+ }
56
+
57
+ override fun removeChild(parent: View, child: View) {
58
+ val state = stateOf(parent)
59
+ val content = state["content_view"] as? FrameLayout
60
+ if (content != null) {
61
+ content.removeView(child)
62
+ } else {
63
+ @Suppress("UNCHECKED_CAST")
64
+ (state["pending"] as? ArrayList<View>)?.remove(child)
65
+ }
66
+ }
67
+
68
+ override fun setFrame(view: View, x: Double, y: Double, width: Double, height: Double) {
69
+ // The dialog owns its own window; the layout engine frames only the children.
70
+ }
71
+
72
+ override fun teardown(view: View) {
73
+ if (stateOf(view)["dialog"] != null) dismiss(view, fromUser = false)
74
+ }
75
+
76
+ private fun present(placeholder: View) {
77
+ val state = stateOf(placeholder)
78
+ val props = propsOf(placeholder)
79
+ val ctx = placeholder.context
80
+ val dialog = Dialog(ctx)
81
+ val content = FrameLayout(ctx)
82
+ val presentation = props.str("presentation_style") ?: "page_sheet"
83
+ val isOverlay = presentation == "overlay" || JsonUtil.truthy(props.value("transparent"))
84
+ content.setBackgroundColor(if (isOverlay) 0x00FFFFFF else 0xFFFFFFFF.toInt())
85
+ dialog.setContentView(content, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
86
+ dialog.window?.let { window ->
87
+ if (isOverlay) {
88
+ window.setBackgroundDrawable(ColorDrawable(0x00000000))
89
+ window.setDimAmount(0.5f)
90
+ window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT)
91
+ } else {
92
+ window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT)
93
+ }
94
+ val animation = props.str("animation_type") ?: props.str("animation")
95
+ when (animation) {
96
+ "none" -> window.setWindowAnimations(0)
97
+ "fade" -> window.setWindowAnimations(android.R.style.Animation_Toast)
98
+ "slide" -> window.setWindowAnimations(android.R.style.Animation_InputMethod)
99
+ }
100
+ PNColor.parse(props.value("status_bar_color"))?.let { window.statusBarColor = it }
101
+ }
102
+ dialog.setCanceledOnTouchOutside(props.value("dismiss_on_backdrop") != false)
103
+ dialog.setCancelable(props.value("dismissable") != false)
104
+ state["dialog"] = dialog
105
+ state["content_view"] = content
106
+ @Suppress("UNCHECKED_CAST")
107
+ val pending = state.remove("pending") as? ArrayList<View>
108
+ pending?.forEach { child ->
109
+ (child.parent as? ViewGroup)?.removeView(child)
110
+ content.addView(child)
111
+ }
112
+ dialog.setOnShowListener { fire(placeholder, "on_show") }
113
+ dialog.setOnDismissListener {
114
+ // Programmatic dismiss (visible=false) also lands here; the
115
+ // Python side expects on_dismiss only for user-driven closes,
116
+ // but android.py fired it unconditionally, so keep that.
117
+ if (stateOf(placeholder)["dialog"] === dialog) {
118
+ stateOf(placeholder).remove("dialog")
119
+ stateOf(placeholder).remove("content_view")
120
+ }
121
+ fire(placeholder, "on_dismiss")
122
+ if (hasEvent(placeholder, "on_request_close")) fire(placeholder, "on_request_close")
123
+ }
124
+ dialog.show()
125
+ }
126
+
127
+ private fun dismiss(placeholder: View, fromUser: Boolean) {
128
+ val state = stateOf(placeholder)
129
+ val dialog = state.remove("dialog") as? Dialog
130
+ state.remove("content_view")
131
+ if (!fromUser) dialog?.setOnDismissListener(null)
132
+ dialog?.dismiss()
133
+ }
134
+ }
@@ -0,0 +1,201 @@
1
+ package com.pythonnative.runtime.components
2
+
3
+ import org.json.JSONArray
4
+ import org.json.JSONObject
5
+
6
+ /**
7
+ * Color parsing shared by every manager.
8
+ *
9
+ * Accepts `#RGB`, `#RGBA`, `#RRGGBB`, `#AARRGGBB` (the Android/Python
10
+ * convention used by `parse_color_int`), `rgb(r, g, b)`,
11
+ * `rgba(r, g, b, a)` with `a` in `0..1`, CSS named colors, packed
12
+ * integers (`0xRRGGBB` gains full alpha), and `[r, g, b(, a)]` arrays.
13
+ * Results are signed 32-bit ARGB ints suitable for Android APIs.
14
+ */
15
+ object PNColor {
16
+ private val named: Map<String, Int> = mapOf(
17
+ "transparent" to 0x00000000,
18
+ "clear" to 0x00000000,
19
+ "black" to 0xFF000000.toInt(),
20
+ "white" to 0xFFFFFFFF.toInt(),
21
+ "red" to 0xFFFF0000.toInt(),
22
+ "green" to 0xFF008000.toInt(),
23
+ "lime" to 0xFF00FF00.toInt(),
24
+ "blue" to 0xFF0000FF.toInt(),
25
+ "yellow" to 0xFFFFFF00.toInt(),
26
+ "cyan" to 0xFF00FFFF.toInt(),
27
+ "aqua" to 0xFF00FFFF.toInt(),
28
+ "magenta" to 0xFFFF00FF.toInt(),
29
+ "fuchsia" to 0xFFFF00FF.toInt(),
30
+ "gray" to 0xFF808080.toInt(),
31
+ "grey" to 0xFF808080.toInt(),
32
+ "darkgray" to 0xFFA9A9A9.toInt(),
33
+ "darkgrey" to 0xFFA9A9A9.toInt(),
34
+ "lightgray" to 0xFFD3D3D3.toInt(),
35
+ "lightgrey" to 0xFFD3D3D3.toInt(),
36
+ "dimgray" to 0xFF696969.toInt(),
37
+ "dimgrey" to 0xFF696969.toInt(),
38
+ "silver" to 0xFFC0C0C0.toInt(),
39
+ "maroon" to 0xFF800000.toInt(),
40
+ "olive" to 0xFF808000.toInt(),
41
+ "navy" to 0xFF000080.toInt(),
42
+ "teal" to 0xFF008080.toInt(),
43
+ "purple" to 0xFF800080.toInt(),
44
+ "orange" to 0xFFFFA500.toInt(),
45
+ "pink" to 0xFFFFC0CB.toInt(),
46
+ "brown" to 0xFFA52A2A.toInt(),
47
+ "gold" to 0xFFFFD700.toInt(),
48
+ "indigo" to 0xFF4B0082.toInt(),
49
+ "violet" to 0xFFEE82EE.toInt(),
50
+ "coral" to 0xFFFF7F50.toInt(),
51
+ "salmon" to 0xFFFA8072.toInt(),
52
+ "tomato" to 0xFFFF6347.toInt(),
53
+ "crimson" to 0xFFDC143C.toInt(),
54
+ "khaki" to 0xFFF0E68C.toInt(),
55
+ "beige" to 0xFFF5F5DC.toInt(),
56
+ "ivory" to 0xFFFFFFF0.toInt(),
57
+ "tan" to 0xFFD2B48C.toInt(),
58
+ "turquoise" to 0xFF40E0D0.toInt(),
59
+ "skyblue" to 0xFF87CEEB.toInt(),
60
+ "steelblue" to 0xFF4682B4.toInt(),
61
+ "royalblue" to 0xFF4169E1.toInt(),
62
+ "dodgerblue" to 0xFF1E90FF.toInt(),
63
+ "slategray" to 0xFF708090.toInt(),
64
+ "slategrey" to 0xFF708090.toInt(),
65
+ "whitesmoke" to 0xFFF5F5F5.toInt(),
66
+ "snow" to 0xFFFFFAFA.toInt(),
67
+ "seagreen" to 0xFF2E8B57.toInt(),
68
+ "forestgreen" to 0xFF228B22.toInt(),
69
+ "darkgreen" to 0xFF006400.toInt(),
70
+ "lightblue" to 0xFFADD8E6.toInt(),
71
+ "lightgreen" to 0xFF90EE90.toInt(),
72
+ "darkblue" to 0xFF00008B.toInt(),
73
+ "darkred" to 0xFF8B0000.toInt(),
74
+ "orangered" to 0xFFFF4500.toInt(),
75
+ "hotpink" to 0xFFFF69B4.toInt(),
76
+ "deeppink" to 0xFFFF1493.toInt(),
77
+ "chocolate" to 0xFFD2691E.toInt(),
78
+ "plum" to 0xFFDDA0DD.toInt(),
79
+ "lavender" to 0xFFE6E6FA.toInt(),
80
+ "mintcream" to 0xFFF5FFFA.toInt(),
81
+ "gainsboro" to 0xFFDCDCDC.toInt(),
82
+ )
83
+
84
+ /** Parse `value` into a signed ARGB int, or `null` when unparseable. */
85
+ fun parse(value: Any?): Int? {
86
+ return when (value) {
87
+ null, JSONObject.NULL -> null
88
+ is Boolean -> null
89
+ is Int -> if (value ushr 24 == 0) value or 0xFF000000.toInt() else value
90
+ is Long -> parseLong(value)
91
+ is Number -> {
92
+ val d = value.toDouble()
93
+ if (d.isNaN() || d.isInfinite()) null else parseLong(d.toLong())
94
+ }
95
+ is String -> parseString(value)
96
+ is JSONArray -> parseArray((0 until value.length()).map { value.opt(it) })
97
+ is List<*> -> parseArray(value)
98
+ else -> null
99
+ }
100
+ }
101
+
102
+ /** Parse `value`, falling back to `default` when unparseable. */
103
+ fun parseOr(value: Any?, default: Int): Int = parse(value) ?: default
104
+
105
+ /** Replace the alpha channel of `color` with `alpha` in `0..1`. */
106
+ fun withAlpha(color: Int, alpha: Double): Int {
107
+ val a = (alpha.coerceIn(0.0, 1.0) * 255.0).toInt()
108
+ return (color and 0x00FFFFFF) or (a shl 24)
109
+ }
110
+
111
+ private fun parseLong(raw: Long): Int {
112
+ val masked = raw and 0xFFFFFFFFL
113
+ val withAlpha = if (masked ushr 24 == 0L) masked or 0xFF000000L else masked
114
+ return withAlpha.toInt()
115
+ }
116
+
117
+ private fun parseArray(items: List<Any?>): Int? {
118
+ if (items.size < 3) return null
119
+ val r = channel(items[0]) ?: return null
120
+ val g = channel(items[1]) ?: return null
121
+ val b = channel(items[2]) ?: return null
122
+ val a = if (items.size >= 4) alphaChannel(items[3]) ?: return null else 255
123
+ return argb(a, r, g, b)
124
+ }
125
+
126
+ private fun parseString(raw: String): Int? {
127
+ val s = raw.trim()
128
+ if (s.isEmpty()) return null
129
+ if (s.startsWith("#")) return parseHex(s.substring(1))
130
+ val lower = s.lowercase()
131
+ named[lower]?.let { return it }
132
+ if (lower.startsWith("rgb")) return parseFunctional(lower)
133
+ if (lower.startsWith("0x")) return s.substring(2).toLongOrNull(16)?.let { parseLong(it) }
134
+ return s.toLongOrNull(16)?.takeIf { s.length == 6 || s.length == 8 }?.let {
135
+ parseHexDigits(s)
136
+ }
137
+ }
138
+
139
+ private fun parseHex(digits: String): Int? {
140
+ if (digits.isEmpty() || !digits.all { it.isLetterOrDigit() }) return null
141
+ val expanded = when (digits.length) {
142
+ 3 -> "FF" + digits.map { "$it$it" }.joinToString("")
143
+ 4 -> {
144
+ // CSS #RGBA: alpha is the last digit.
145
+ val rgb = digits.substring(0, 3).map { "$it$it" }.joinToString("")
146
+ val a = "${digits[3]}${digits[3]}"
147
+ a + rgb
148
+ }
149
+ 6 -> "FF$digits"
150
+ 8 -> digits
151
+ else -> return null
152
+ }
153
+ return expanded.toLongOrNull(16)?.toInt()
154
+ }
155
+
156
+ private fun parseHexDigits(digits: String): Int? = parseHex(digits)
157
+
158
+ private fun parseFunctional(lower: String): Int? {
159
+ val open = lower.indexOf('(')
160
+ val close = lower.lastIndexOf(')')
161
+ if (open < 0 || close < open) return null
162
+ val parts = lower.substring(open + 1, close).split(',', '/', ' ').map { it.trim() }.filter { it.isNotEmpty() }
163
+ if (parts.size < 3) return null
164
+ val r = channel(parts[0]) ?: return null
165
+ val g = channel(parts[1]) ?: return null
166
+ val b = channel(parts[2]) ?: return null
167
+ val a = if (parts.size >= 4) alphaChannel(parts[3]) ?: return null else 255
168
+ return argb(a, r, g, b)
169
+ }
170
+
171
+ private fun channel(value: Any?): Int? {
172
+ val d = when (value) {
173
+ is Number -> value.toDouble()
174
+ is String -> {
175
+ val t = value.trim()
176
+ if (t.endsWith("%")) (t.dropLast(1).toDoubleOrNull() ?: return null) * 2.55
177
+ else t.toDoubleOrNull() ?: return null
178
+ }
179
+ else -> return null
180
+ }
181
+ return d.toInt().coerceIn(0, 255)
182
+ }
183
+
184
+ private fun alphaChannel(value: Any?): Int? {
185
+ val d = when (value) {
186
+ is Number -> value.toDouble()
187
+ is String -> {
188
+ val t = value.trim()
189
+ if (t.endsWith("%")) (t.dropLast(1).toDoubleOrNull() ?: return null) / 100.0
190
+ else t.toDoubleOrNull() ?: return null
191
+ }
192
+ else -> return null
193
+ }
194
+ // Values above 1 are taken as 0..255 bytes.
195
+ val a = if (d > 1.0) d / 255.0 else d
196
+ return (a.coerceIn(0.0, 1.0) * 255.0 + 0.5).toInt()
197
+ }
198
+
199
+ private fun argb(a: Int, r: Int, g: Int, b: Int): Int =
200
+ (a shl 24) or (r shl 16) or (g shl 8) or b
201
+ }
@@ -0,0 +1,86 @@
1
+ package com.pythonnative.runtime.components
2
+
3
+ import android.content.Context
4
+ import android.view.View
5
+ import android.widget.AdapterView
6
+ import android.widget.ArrayAdapter
7
+ import android.widget.Spinner
8
+ import com.pythonnative.runtime.bridge.JsonUtil
9
+ import com.pythonnative.runtime.bridge.str
10
+ import com.pythonnative.runtime.bridge.value
11
+ import org.json.JSONArray
12
+ import org.json.JSONObject
13
+
14
+ /** `Picker` element: a native `Spinner` dropdown over `items` of `{label, value}`. */
15
+ class PickerManager : ComponentManager() {
16
+ override fun createView(context: Context, tag: Long, props: JSONObject): View {
17
+ val spinner = Spinner(context)
18
+ spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
19
+ override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
20
+ if (stateOf(parent)["suppress"] == true) return
21
+ val items = propsOf(parent).value("items") as? JSONArray ?: return
22
+ if (position < 0 || position >= items.length()) return
23
+ fire(parent, "on_change", itemValue(items.opt(position)))
24
+ }
25
+
26
+ override fun onNothingSelected(parent: AdapterView<*>) {}
27
+ }
28
+ return spinner
29
+ }
30
+
31
+ private fun itemValue(item: Any?): Any? = when (item) {
32
+ is JSONObject -> item.value("value")
33
+ JSONObject.NULL -> null
34
+ else -> item
35
+ }
36
+
37
+ private fun itemLabel(item: Any?): String = when (item) {
38
+ is JSONObject -> item.str("label") ?: item.str("value") ?: ""
39
+ null, JSONObject.NULL -> ""
40
+ else -> item.toString()
41
+ }
42
+
43
+ override fun applyProps(view: View, props: JSONObject, initial: Boolean) {
44
+ val spinner = view as Spinner
45
+ val state = stateOf(spinner)
46
+ val merged = propsOf(spinner)
47
+ val items = merged.value("items") as? JSONArray ?: JSONArray()
48
+ if (props.has("items") || initial) {
49
+ val labels = (0 until items.length()).map { itemLabel(items.opt(it)) }
50
+ val adapter = ArrayAdapter(spinner.context, android.R.layout.simple_spinner_item, labels)
51
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
52
+ state["suppress"] = true
53
+ try {
54
+ spinner.adapter = adapter
55
+ } finally {
56
+ state["suppress"] = false
57
+ }
58
+ }
59
+ if (props.has("value") || props.has("selected_value") || initial) {
60
+ val value = merged.value("value") ?: merged.value("selected_value")
61
+ var target = -1
62
+ for (i in 0 until items.length()) {
63
+ if (valuesEqual(itemValue(items.opt(i)), value)) {
64
+ target = i
65
+ break
66
+ }
67
+ }
68
+ if (target >= 0 && spinner.selectedItemPosition != target) {
69
+ state["suppress"] = true
70
+ try {
71
+ spinner.setSelection(target, false)
72
+ } finally {
73
+ state["suppress"] = false
74
+ }
75
+ }
76
+ }
77
+ if (props.has("disabled")) spinner.isEnabled = !JsonUtil.truthy(props.value("disabled"))
78
+ ViewStyler.apply(spinner, props)
79
+ }
80
+
81
+ private fun valuesEqual(a: Any?, b: Any?): Boolean {
82
+ if (a == b) return true
83
+ if (a is Number && b is Number) return a.toDouble() == b.toDouble()
84
+ return a != null && b != null && a.toString() == b.toString()
85
+ }
86
+ }
@@ -0,0 +1,55 @@
1
+ package com.pythonnative.runtime.components
2
+
3
+ import android.content.Context
4
+ import android.view.View
5
+ import android.view.ViewGroup
6
+ import android.widget.FrameLayout
7
+ import com.pythonnative.runtime.screens.ScreenRegistry
8
+ import org.json.JSONObject
9
+
10
+ /**
11
+ * `Portal` element: floats its children over the screen in a full-size,
12
+ * non-clickable overlay added directly to the screen's fragment
13
+ * container (the same parent as the screen root, so portal coordinates
14
+ * equal viewport coordinates). The overlay attaches lazily on the first
15
+ * child insert and re-homes itself if the container changed.
16
+ */
17
+ class PortalManager : ComponentManager() {
18
+ override fun createView(context: Context, tag: Long, props: JSONObject): View {
19
+ val overlay = FrameLayout(context)
20
+ overlay.isClickable = false
21
+ return overlay
22
+ }
23
+
24
+ override fun applyProps(view: View, props: JSONObject, initial: Boolean) {
25
+ ViewStyler.apply(view, props)
26
+ if (!initial) ensureAttached(view)
27
+ }
28
+
29
+ private fun ensureAttached(overlay: View) {
30
+ val container = ScreenRegistry.activeContainer() ?: return
31
+ val parent = overlay.parent as? ViewGroup
32
+ if (parent === container) {
33
+ overlay.bringToFront()
34
+ return
35
+ }
36
+ parent?.removeView(overlay)
37
+ container.addView(
38
+ overlay,
39
+ ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT),
40
+ )
41
+ }
42
+
43
+ override fun insertChild(parent: View, child: View, index: Int) {
44
+ ensureAttached(parent)
45
+ ViewChildren.insert(parent as ViewGroup, child, index)
46
+ }
47
+
48
+ override fun setFrame(view: View, x: Double, y: Double, width: Double, height: Double) {
49
+ // The overlay fills its container; the engine frames only the portal's children.
50
+ }
51
+
52
+ override fun teardown(view: View) {
53
+ (view.parent as? ViewGroup)?.removeView(view)
54
+ }
55
+ }
@@ -0,0 +1,122 @@
1
+ package com.pythonnative.runtime.components
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.content.Context
5
+ import android.content.res.ColorStateList
6
+ import android.graphics.drawable.RippleDrawable
7
+ import android.view.MotionEvent
8
+ import android.view.View
9
+ import android.view.ViewConfiguration
10
+ import com.pythonnative.runtime.bridge.JsonUtil
11
+ import com.pythonnative.runtime.bridge.MainThread
12
+ import com.pythonnative.runtime.bridge.num
13
+ import com.pythonnative.runtime.bridge.value
14
+ import com.pythonnative.runtime.gestures.GestureCoordinator
15
+ import com.pythonnative.runtime.views.PNFrameLayout
16
+ import org.json.JSONObject
17
+ import kotlin.math.hypot
18
+
19
+ /**
20
+ * `Pressable` element: a container dispatching press events from one
21
+ * touch stream. `on_press_in` at finger-down (plus an opacity dip),
22
+ * `on_long_press` after the long-press timeout, `on_press` on a clean
23
+ * release, and `on_press_out` when the finger lifts or the touch
24
+ * cancels. The same stream feeds the gesture coordinator so press
25
+ * feedback and pan/pinch recognition coexist on one view.
26
+ */
27
+ class PressableManager : ViewManager() {
28
+ private class Press(val downX: Double, val downY: Double, val seq: Int) {
29
+ var moved = false
30
+ var longFired = false
31
+ }
32
+
33
+ @SuppressLint("ClickableViewAccessibility")
34
+ override fun createView(context: Context, tag: Long, props: JSONObject): View {
35
+ val view = PNFrameLayout(context)
36
+ view.isClickable = true
37
+ view.isFocusable = true
38
+ view.setOnTouchListener { v, event -> onTouch(v, event) }
39
+ return view
40
+ }
41
+
42
+ override fun applyProps(view: View, props: JSONObject, initial: Boolean) {
43
+ // Press handling owns the touch listener; gesture specs are fed from inside it.
44
+ stateOf(view)["gestures_bound"] = true
45
+ super.applyProps(view, props, initial)
46
+ if (props.has("ripple") || props.has("android_ripple")) applyRipple(view, props)
47
+ if (props.has("disabled")) view.isEnabled = !JsonUtil.truthy(props.value("disabled"))
48
+ }
49
+
50
+ private fun applyRipple(view: View, props: JSONObject) {
51
+ val spec = props.value("android_ripple") ?: props.value("ripple")
52
+ if (spec == null || spec == false) {
53
+ view.foreground = null
54
+ return
55
+ }
56
+ val color = when (spec) {
57
+ is JSONObject -> PNColor.parse(spec.value("color"))
58
+ else -> PNColor.parse(spec)
59
+ } ?: 0x33000000
60
+ val borderless = (spec as? JSONObject)?.let { JsonUtil.truthy(it.value("borderless")) } ?: false
61
+ val mask = if (borderless) null else android.graphics.drawable.ColorDrawable(0xFFFFFFFF.toInt())
62
+ view.foreground = RippleDrawable(ColorStateList.valueOf(color), null, mask)
63
+ }
64
+
65
+ private fun onTouch(view: View, event: MotionEvent): Boolean {
66
+ if (ViewStyler.pointerEventsBlocked(view)) return false
67
+ val record = recordOf(view) ?: return false
68
+ GestureCoordinator.feed(record, event)
69
+ if (!view.isEnabled) return true
70
+ val state = record.state
71
+ val merged = record.props
72
+ val density = view.resources.displayMetrics.density
73
+ val x = event.x / density
74
+ val y = event.y / density
75
+ when (event.actionMasked) {
76
+ MotionEvent.ACTION_DOWN -> {
77
+ val seq = ((state["press_seq"] as? Int) ?: 0) + 1
78
+ val press = Press(x.toDouble(), y.toDouble(), seq)
79
+ state["press"] = press
80
+ state["press_seq"] = seq
81
+ fire(view, "on_press_in")
82
+ val opacity = merged.num("pressed_opacity") ?: merged.num("active_opacity") ?: 0.6
83
+ if (opacity < 1.0) view.animate().alpha(opacity.toFloat()).setDuration(50).start()
84
+ if (hasEvent(view, "on_long_press")) {
85
+ val delay = merged.num("delay_long_press")?.toLong() ?: ViewConfiguration.getLongPressTimeout().toLong().coerceAtLeast(500L)
86
+ MainThread.postDelayed({
87
+ val live = recordOf(view)?.state?.get("press") as? Press ?: return@postDelayed
88
+ if (live.seq != seq || live.moved || live.longFired) return@postDelayed
89
+ live.longFired = true
90
+ fire(view, "on_long_press")
91
+ }, delay)
92
+ }
93
+ view.isPressed = true
94
+ return true
95
+ }
96
+ MotionEvent.ACTION_MOVE -> {
97
+ val press = state["press"] as? Press ?: return true
98
+ val slop = merged.num("tap_slop") ?: TAP_SLOP_DP
99
+ if (hypot(x - press.downX, y - press.downY) > slop) press.moved = true
100
+ return true
101
+ }
102
+ MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
103
+ val press = state["press"] as? Press
104
+ state["press"] = null
105
+ view.isPressed = false
106
+ if (press == null) return true
107
+ fire(view, "on_press_out")
108
+ view.animate().alpha(1f).setDuration(100).start()
109
+ if (event.actionMasked == MotionEvent.ACTION_UP && !press.moved && !press.longFired) {
110
+ view.performClick()
111
+ fire(view, "on_press")
112
+ }
113
+ return true
114
+ }
115
+ }
116
+ return true
117
+ }
118
+
119
+ private companion object {
120
+ const val TAP_SLOP_DP = 12.0
121
+ }
122
+ }