bootstack 0.1.0__py3-none-any.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 (471) hide show
  1. bootstack/__init__.py +157 -0
  2. bootstack/__main__.py +5 -0
  3. bootstack/_core/__init__.py +21 -0
  4. bootstack/_core/capabilities/__init__.py +45 -0
  5. bootstack/_core/capabilities/after.py +103 -0
  6. bootstack/_core/capabilities/bind.py +192 -0
  7. bootstack/_core/capabilities/bindtags.py +112 -0
  8. bootstack/_core/capabilities/busy.py +72 -0
  9. bootstack/_core/capabilities/clipboard.py +89 -0
  10. bootstack/_core/capabilities/focus.py +118 -0
  11. bootstack/_core/capabilities/grab.py +65 -0
  12. bootstack/_core/capabilities/grid.py +211 -0
  13. bootstack/_core/capabilities/localization.py +231 -0
  14. bootstack/_core/capabilities/pack.py +140 -0
  15. bootstack/_core/capabilities/place.py +113 -0
  16. bootstack/_core/capabilities/selection.py +136 -0
  17. bootstack/_core/capabilities/signals.py +244 -0
  18. bootstack/_core/capabilities/winfo.py +315 -0
  19. bootstack/_core/colorutils.py +234 -0
  20. bootstack/_core/exceptions.py +25 -0
  21. bootstack/_core/images.py +463 -0
  22. bootstack/_core/mixins/__init__.py +1 -0
  23. bootstack/_core/mixins/ttk_state.py +35 -0
  24. bootstack/_core/mixins/widget.py +132 -0
  25. bootstack/_core/paths.py +49 -0
  26. bootstack/_core/publisher.py +149 -0
  27. bootstack/_core/variables.py +62 -0
  28. bootstack/_runtime/__init__.py +3 -0
  29. bootstack/_runtime/app.py +930 -0
  30. bootstack/_runtime/base_window.py +945 -0
  31. bootstack/_runtime/events.py +399 -0
  32. bootstack/_runtime/shortcuts.py +496 -0
  33. bootstack/_runtime/tk_patch.py +43 -0
  34. bootstack/_runtime/toplevel.py +276 -0
  35. bootstack/_runtime/utility.py +457 -0
  36. bootstack/_runtime/visual_focus.py +240 -0
  37. bootstack/_runtime/window_utilities.py +1123 -0
  38. bootstack/assets/__init__.py +21 -0
  39. bootstack/assets/bootstack.ico +0 -0
  40. bootstack/assets/bootstack.png +0 -0
  41. bootstack/assets/elements/__init__.py +0 -0
  42. bootstack/assets/elements/badge-pill.png +0 -0
  43. bootstack/assets/elements/badge-square.png +0 -0
  44. bootstack/assets/elements/button-compact.png +0 -0
  45. bootstack/assets/elements/button-default.png +0 -0
  46. bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
  47. bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
  48. bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
  49. bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
  50. bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
  51. bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
  52. bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
  53. bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
  54. bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
  55. bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
  56. bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
  57. bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
  58. bootstack/assets/elements/card.png +0 -0
  59. bootstack/assets/elements/checkbox-checked.png +0 -0
  60. bootstack/assets/elements/checkbox-indeterminate.png +0 -0
  61. bootstack/assets/elements/checkbox-unchecked.png +0 -0
  62. bootstack/assets/elements/field.png +0 -0
  63. bootstack/assets/elements/input-addon-compact.png +0 -0
  64. bootstack/assets/elements/input-addon-default.png +0 -0
  65. bootstack/assets/elements/input-compact.png +0 -0
  66. bootstack/assets/elements/input-default.png +0 -0
  67. bootstack/assets/elements/list-item-separated.png +0 -0
  68. bootstack/assets/elements/list-item.png +0 -0
  69. bootstack/assets/elements/listrow-compact.png +0 -0
  70. bootstack/assets/elements/listrow-default.png +0 -0
  71. bootstack/assets/elements/manifest.toml +361 -0
  72. bootstack/assets/elements/menu-item.png +0 -0
  73. bootstack/assets/elements/navitem-compact.png +0 -0
  74. bootstack/assets/elements/navitem-default.png +0 -0
  75. bootstack/assets/elements/progressbar-h-compact.png +0 -0
  76. bootstack/assets/elements/progressbar-h-default.png +0 -0
  77. bootstack/assets/elements/progressbar-v-compact.png +0 -0
  78. bootstack/assets/elements/progressbar-v-default.png +0 -0
  79. bootstack/assets/elements/radiobutton.png +0 -0
  80. bootstack/assets/elements/scrollbar-horizontal.png +0 -0
  81. bootstack/assets/elements/scrollbar-vertical.png +0 -0
  82. bootstack/assets/elements/slider-handle.png +0 -0
  83. bootstack/assets/elements/slider-track-h.png +0 -0
  84. bootstack/assets/elements/slider-track-v.png +0 -0
  85. bootstack/assets/elements/switch-off.png +0 -0
  86. bootstack/assets/elements/switch-on.png +0 -0
  87. bootstack/assets/elements/tab-h.png +0 -0
  88. bootstack/assets/elements/tab-v.png +0 -0
  89. bootstack/assets/icons/bootstrap.ttf +0 -0
  90. bootstack/assets/icons/glyphmap.json +2080 -0
  91. bootstack/assets/icons/icon_metrics.json +12470 -0
  92. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
  93. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +856 -0
  94. bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
  95. bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +878 -0
  96. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
  97. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +856 -0
  98. bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
  99. bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +856 -0
  100. bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
  101. bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +856 -0
  102. bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
  103. bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +878 -0
  104. bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
  105. bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +856 -0
  106. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
  107. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +856 -0
  108. bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
  109. bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +854 -0
  110. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
  111. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +845 -0
  112. bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
  113. bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +844 -0
  114. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
  115. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +917 -0
  116. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
  117. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +845 -0
  118. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
  119. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +844 -0
  120. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
  121. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +844 -0
  122. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
  123. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +845 -0
  124. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
  125. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +845 -0
  126. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
  127. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +845 -0
  128. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
  129. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +845 -0
  130. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
  131. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +845 -0
  132. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
  133. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +845 -0
  134. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
  135. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +845 -0
  136. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
  137. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +845 -0
  138. bootstack/cli/__init__.py +133 -0
  139. bootstack/cli/__main__.py +6 -0
  140. bootstack/cli/add.py +395 -0
  141. bootstack/cli/appicon.py +285 -0
  142. bootstack/cli/build.py +115 -0
  143. bootstack/cli/config.py +313 -0
  144. bootstack/cli/demo.py +564 -0
  145. bootstack/cli/dev.py +153 -0
  146. bootstack/cli/doctor.py +195 -0
  147. bootstack/cli/icons.py +98 -0
  148. bootstack/cli/promote.py +120 -0
  149. bootstack/cli/pyinstaller.py +268 -0
  150. bootstack/cli/run.py +95 -0
  151. bootstack/cli/start.py +117 -0
  152. bootstack/cli/templates/__init__.py +931 -0
  153. bootstack/clipboard.py +48 -0
  154. bootstack/constants.py +318 -0
  155. bootstack/data/README.md +615 -0
  156. bootstack/data/__init__.py +78 -0
  157. bootstack/data/_observable.py +276 -0
  158. bootstack/data/base.py +780 -0
  159. bootstack/data/file_source.py +367 -0
  160. bootstack/data/memory_source.py +450 -0
  161. bootstack/data/query.py +367 -0
  162. bootstack/data/readers.py +289 -0
  163. bootstack/data/sqlite_source.py +869 -0
  164. bootstack/data/types.py +354 -0
  165. bootstack/data/writers.py +232 -0
  166. bootstack/dev/__init__.py +36 -0
  167. bootstack/dev/_capture.py +141 -0
  168. bootstack/dev/_env.py +43 -0
  169. bootstack/dev/_registry.py +140 -0
  170. bootstack/dev/_reloader.py +351 -0
  171. bootstack/dev/_reset.py +50 -0
  172. bootstack/dev/_watcher.py +91 -0
  173. bootstack/dialogs/__init__.py +948 -0
  174. bootstack/dialogs/_impl/__init__.py +47 -0
  175. bootstack/dialogs/_impl/colorchooser.py +588 -0
  176. bootstack/dialogs/_impl/datedialog.py +450 -0
  177. bootstack/dialogs/_impl/dialog.py +594 -0
  178. bootstack/dialogs/_impl/filterdialog.py +358 -0
  179. bootstack/dialogs/_impl/fontdialog.py +364 -0
  180. bootstack/dialogs/_impl/formdialog.py +564 -0
  181. bootstack/dialogs/_impl/message.py +486 -0
  182. bootstack/dialogs/_impl/query.py +570 -0
  183. bootstack/errors.py +67 -0
  184. bootstack/events/__init__.py +111 -0
  185. bootstack/events/_event.py +135 -0
  186. bootstack/events/_payloads.py +539 -0
  187. bootstack/events/_subscription.py +38 -0
  188. bootstack/i18n/README.md +77 -0
  189. bootstack/i18n/__init__.py +23 -0
  190. bootstack/i18n/catalog.py +121 -0
  191. bootstack/i18n/intl_format.py +584 -0
  192. bootstack/i18n/msgcat.py +425 -0
  193. bootstack/i18n/specs.py +156 -0
  194. bootstack/images.py +563 -0
  195. bootstack/py.typed +1 -0
  196. bootstack/scheduling/__init__.py +11 -0
  197. bootstack/scheduling/_schedule.py +218 -0
  198. bootstack/shortcuts.py +21 -0
  199. bootstack/signals/README.md +98 -0
  200. bootstack/signals/__init__.py +10 -0
  201. bootstack/signals/integration.py +100 -0
  202. bootstack/signals/signal.py +353 -0
  203. bootstack/signals/types.py +6 -0
  204. bootstack/store.py +286 -0
  205. bootstack/streams/__init__.py +12 -0
  206. bootstack/streams/_stream.py +321 -0
  207. bootstack/style/__init__.py +38 -0
  208. bootstack/style/builders/__init__.py +51 -0
  209. bootstack/style/builders/badge.py +46 -0
  210. bootstack/style/builders/button.py +339 -0
  211. bootstack/style/builders/buttongroup.py +311 -0
  212. bootstack/style/builders/calendar.py +271 -0
  213. bootstack/style/builders/checkbutton.py +110 -0
  214. bootstack/style/builders/combobox.py +113 -0
  215. bootstack/style/builders/contextmenu.py +268 -0
  216. bootstack/style/builders/entry.py +82 -0
  217. bootstack/style/builders/expander.py +148 -0
  218. bootstack/style/builders/field.py +335 -0
  219. bootstack/style/builders/frame.py +50 -0
  220. bootstack/style/builders/label.py +28 -0
  221. bootstack/style/builders/labelframe.py +34 -0
  222. bootstack/style/builders/listview.py +369 -0
  223. bootstack/style/builders/menubar.py +91 -0
  224. bootstack/style/builders/menubutton.py +359 -0
  225. bootstack/style/builders/panedwindow.py +25 -0
  226. bootstack/style/builders/progressbar.py +67 -0
  227. bootstack/style/builders/radiobutton.py +99 -0
  228. bootstack/style/builders/scale.py +64 -0
  229. bootstack/style/builders/scrollbar.py +225 -0
  230. bootstack/style/builders/separator.py +49 -0
  231. bootstack/style/builders/sidenav.py +643 -0
  232. bootstack/style/builders/sizegrip.py +15 -0
  233. bootstack/style/builders/spinbox.py +119 -0
  234. bootstack/style/builders/switch.py +70 -0
  235. bootstack/style/builders/tabitem.py +204 -0
  236. bootstack/style/builders/togglegroup.py +294 -0
  237. bootstack/style/builders/toolbutton.py +275 -0
  238. bootstack/style/builders/tooltip.py +26 -0
  239. bootstack/style/builders/treeview.py +193 -0
  240. bootstack/style/builders/utils.py +455 -0
  241. bootstack/style/builders_tk/__init__.py +16 -0
  242. bootstack/style/builders_tk/defaults.py +229 -0
  243. bootstack/style/element.py +173 -0
  244. bootstack/style/fonts.py +123 -0
  245. bootstack/style/style.py +609 -0
  246. bootstack/style/style_builder_base.py +716 -0
  247. bootstack/style/style_builder_mixed.py +93 -0
  248. bootstack/style/style_builder_tk.py +109 -0
  249. bootstack/style/style_builder_ttk.py +353 -0
  250. bootstack/style/style_resolver.py +447 -0
  251. bootstack/style/theme.py +245 -0
  252. bootstack/style/theme_provider.py +471 -0
  253. bootstack/style/themes/__init__.py +128 -0
  254. bootstack/style/tk_patch.py +5 -0
  255. bootstack/style/token_maps.py +41 -0
  256. bootstack/style/types.py +32 -0
  257. bootstack/style/typography.py +523 -0
  258. bootstack/style/utility.py +746 -0
  259. bootstack/types.py +39 -0
  260. bootstack/validation/__init__.py +6 -0
  261. bootstack/validation/types.py +15 -0
  262. bootstack/validation/validation_result.py +17 -0
  263. bootstack/validation/validation_rules.py +205 -0
  264. bootstack/widgets/__init__.py +74 -0
  265. bootstack/widgets/_core/__init__.py +31 -0
  266. bootstack/widgets/_core/app_config.py +266 -0
  267. bootstack/widgets/_core/base.py +461 -0
  268. bootstack/widgets/_core/container.py +334 -0
  269. bootstack/widgets/_core/context.py +35 -0
  270. bootstack/widgets/_core/events.py +130 -0
  271. bootstack/widgets/_core/field_mixin.py +353 -0
  272. bootstack/widgets/_core/icon_image_props.py +72 -0
  273. bootstack/widgets/_core/image_binding.py +93 -0
  274. bootstack/widgets/_core/navmodel.py +345 -0
  275. bootstack/widgets/_core/options.py +210 -0
  276. bootstack/widgets/_core/selection_group.py +130 -0
  277. bootstack/widgets/_core/window_controls.py +96 -0
  278. bootstack/widgets/_core/window_menu.py +246 -0
  279. bootstack/widgets/_impl/__init__.py +1 -0
  280. bootstack/widgets/_impl/_internal/__init__.py +0 -0
  281. bootstack/widgets/_impl/_internal/wrapper_base.py +307 -0
  282. bootstack/widgets/_impl/_parts/__init__.py +11 -0
  283. bootstack/widgets/_impl/_parts/numberentry_part.py +385 -0
  284. bootstack/widgets/_impl/_parts/spinnerentry_part.py +434 -0
  285. bootstack/widgets/_impl/_parts/textentry_part.py +406 -0
  286. bootstack/widgets/_impl/composites/__init__.py +33 -0
  287. bootstack/widgets/_impl/composites/_dateutils.py +33 -0
  288. bootstack/widgets/_impl/composites/_image_fit.py +105 -0
  289. bootstack/widgets/_impl/composites/accordion.py +381 -0
  290. bootstack/widgets/_impl/composites/avatar.py +191 -0
  291. bootstack/widgets/_impl/composites/buttongroup.py +371 -0
  292. bootstack/widgets/_impl/composites/calendar.py +972 -0
  293. bootstack/widgets/_impl/composites/carousel.py +567 -0
  294. bootstack/widgets/_impl/composites/chart.py +882 -0
  295. bootstack/widgets/_impl/composites/compositeframe.py +298 -0
  296. bootstack/widgets/_impl/composites/contextmenu.py +1951 -0
  297. bootstack/widgets/_impl/composites/dateentry.py +404 -0
  298. bootstack/widgets/_impl/composites/dropdownbutton.py +325 -0
  299. bootstack/widgets/_impl/composites/expander.py +515 -0
  300. bootstack/widgets/_impl/composites/field.py +670 -0
  301. bootstack/widgets/_impl/composites/form.py +1066 -0
  302. bootstack/widgets/_impl/composites/gallery.py +551 -0
  303. bootstack/widgets/_impl/composites/list/__init__.py +15 -0
  304. bootstack/widgets/_impl/composites/list/listitem.py +802 -0
  305. bootstack/widgets/_impl/composites/list/listview.py +1433 -0
  306. bootstack/widgets/_impl/composites/menu/__init__.py +18 -0
  307. bootstack/widgets/_impl/composites/menu/model.py +358 -0
  308. bootstack/widgets/_impl/composites/menu/render_native.py +134 -0
  309. bootstack/widgets/_impl/composites/menu/render_themed.py +134 -0
  310. bootstack/widgets/_impl/composites/meter.py +860 -0
  311. bootstack/widgets/_impl/composites/numericentry.py +201 -0
  312. bootstack/widgets/_impl/composites/pagestack.py +395 -0
  313. bootstack/widgets/_impl/composites/passwordentry.py +142 -0
  314. bootstack/widgets/_impl/composites/pathentry.py +168 -0
  315. bootstack/widgets/_impl/composites/picture.py +289 -0
  316. bootstack/widgets/_impl/composites/radiogroup.py +511 -0
  317. bootstack/widgets/_impl/composites/scrolledtext.py +375 -0
  318. bootstack/widgets/_impl/composites/scrolledtext.pyi +186 -0
  319. bootstack/widgets/_impl/composites/scrollview.py +764 -0
  320. bootstack/widgets/_impl/composites/selectbox.py +1026 -0
  321. bootstack/widgets/_impl/composites/shell/__init__.py +40 -0
  322. bootstack/widgets/_impl/composites/shell/content_host.py +52 -0
  323. bootstack/widgets/_impl/composites/shell/layout.py +335 -0
  324. bootstack/widgets/_impl/composites/shell/nav_panel.py +345 -0
  325. bootstack/widgets/_impl/composites/shell/providers.py +558 -0
  326. bootstack/widgets/_impl/composites/shell/rail.py +117 -0
  327. bootstack/widgets/_impl/composites/shell/shell.py +581 -0
  328. bootstack/widgets/_impl/composites/shell/workspace.py +273 -0
  329. bootstack/widgets/_impl/composites/sidenav/__init__.py +16 -0
  330. bootstack/widgets/_impl/composites/sidenav/header.py +81 -0
  331. bootstack/widgets/_impl/composites/sidenav/separator.py +44 -0
  332. bootstack/widgets/_impl/composites/slider/__init__.py +7 -0
  333. bootstack/widgets/_impl/composites/slider/_shared.py +195 -0
  334. bootstack/widgets/_impl/composites/slider/rangeslider.py +982 -0
  335. bootstack/widgets/_impl/composites/slider/slider.py +851 -0
  336. bootstack/widgets/_impl/composites/spinnerentry.py +185 -0
  337. bootstack/widgets/_impl/composites/tableview/__init__.py +5 -0
  338. bootstack/widgets/_impl/composites/tableview/tableview.py +3388 -0
  339. bootstack/widgets/_impl/composites/tableview/types.py +169 -0
  340. bootstack/widgets/_impl/composites/tabs/__init__.py +23 -0
  341. bootstack/widgets/_impl/composites/tabs/tabitem.py +389 -0
  342. bootstack/widgets/_impl/composites/tabs/tabs.py +974 -0
  343. bootstack/widgets/_impl/composites/tabs/tabview.py +650 -0
  344. bootstack/widgets/_impl/composites/textarea/__init__.py +26 -0
  345. bootstack/widgets/_impl/composites/textarea/change.py +46 -0
  346. bootstack/widgets/_impl/composites/textarea/codeeditor.py +526 -0
  347. bootstack/widgets/_impl/composites/textarea/core.py +495 -0
  348. bootstack/widgets/_impl/composites/textarea/decoration.py +42 -0
  349. bootstack/widgets/_impl/composites/textarea/diff.py +127 -0
  350. bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +1 -0
  351. bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +138 -0
  352. bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +158 -0
  353. bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +138 -0
  354. bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +312 -0
  355. bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +177 -0
  356. bootstack/widgets/_impl/composites/textarea/filter.py +171 -0
  357. bootstack/widgets/_impl/composites/textarea/search_overlay.py +459 -0
  358. bootstack/widgets/_impl/composites/textarea/sidebar.py +88 -0
  359. bootstack/widgets/_impl/composites/textarea/style_registry.py +178 -0
  360. bootstack/widgets/_impl/composites/textarea/textarea.py +606 -0
  361. bootstack/widgets/_impl/composites/textarea/undo.py +217 -0
  362. bootstack/widgets/_impl/composites/textentry.py +57 -0
  363. bootstack/widgets/_impl/composites/timeentry.py +176 -0
  364. bootstack/widgets/_impl/composites/toast.py +390 -0
  365. bootstack/widgets/_impl/composites/toast_stack.py +156 -0
  366. bootstack/widgets/_impl/composites/togglegroup.py +418 -0
  367. bootstack/widgets/_impl/composites/toolbar.py +608 -0
  368. bootstack/widgets/_impl/composites/tooltip.py +491 -0
  369. bootstack/widgets/_impl/composites/tree/__init__.py +7 -0
  370. bootstack/widgets/_impl/composites/tree/source_binding.py +136 -0
  371. bootstack/widgets/_impl/composites/tree/treeitem.py +393 -0
  372. bootstack/widgets/_impl/composites/tree/treenode.py +174 -0
  373. bootstack/widgets/_impl/composites/tree/treeview.py +841 -0
  374. bootstack/widgets/_impl/mixins/__init__.py +24 -0
  375. bootstack/widgets/_impl/mixins/configure_mixin.py +216 -0
  376. bootstack/widgets/_impl/mixins/entry_mixin.py +134 -0
  377. bootstack/widgets/_impl/mixins/font_mixin.py +368 -0
  378. bootstack/widgets/_impl/mixins/icon_mixin.py +61 -0
  379. bootstack/widgets/_impl/mixins/localization_mixin.py +253 -0
  380. bootstack/widgets/_impl/mixins/signal_mixin.py +268 -0
  381. bootstack/widgets/_impl/mixins/validation_mixin.py +226 -0
  382. bootstack/widgets/_impl/primitives/__init__.py +49 -0
  383. bootstack/widgets/_impl/primitives/_menubutton.py +107 -0
  384. bootstack/widgets/_impl/primitives/badge.py +45 -0
  385. bootstack/widgets/_impl/primitives/button.py +76 -0
  386. bootstack/widgets/_impl/primitives/card.py +45 -0
  387. bootstack/widgets/_impl/primitives/checkbutton.py +124 -0
  388. bootstack/widgets/_impl/primitives/checktoggle.py +62 -0
  389. bootstack/widgets/_impl/primitives/combobox.py +156 -0
  390. bootstack/widgets/_impl/primitives/entry.py +87 -0
  391. bootstack/widgets/_impl/primitives/flexframe.py +448 -0
  392. bootstack/widgets/_impl/primitives/frame.py +185 -0
  393. bootstack/widgets/_impl/primitives/gridframe.py +546 -0
  394. bootstack/widgets/_impl/primitives/label.py +84 -0
  395. bootstack/widgets/_impl/primitives/labelframe.py +54 -0
  396. bootstack/widgets/_impl/primitives/optionmenu.py +387 -0
  397. bootstack/widgets/_impl/primitives/packframe.py +227 -0
  398. bootstack/widgets/_impl/primitives/panedwindow.py +45 -0
  399. bootstack/widgets/_impl/primitives/progressbar.py +83 -0
  400. bootstack/widgets/_impl/primitives/radiobutton.py +115 -0
  401. bootstack/widgets/_impl/primitives/radiotoggle.py +54 -0
  402. bootstack/widgets/_impl/primitives/scrollbar.py +42 -0
  403. bootstack/widgets/_impl/primitives/separator.py +43 -0
  404. bootstack/widgets/_impl/primitives/sizegrip.py +33 -0
  405. bootstack/widgets/_impl/primitives/spinbox.py +95 -0
  406. bootstack/widgets/_impl/primitives/switch.py +44 -0
  407. bootstack/widgets/_impl/primitives/treeview.py +69 -0
  408. bootstack/widgets/app.py +371 -0
  409. bootstack/widgets/appshell.py +1179 -0
  410. bootstack/widgets/avatar.py +140 -0
  411. bootstack/widgets/boolean_controls.py +455 -0
  412. bootstack/widgets/button.py +224 -0
  413. bootstack/widgets/buttongroup.py +239 -0
  414. bootstack/widgets/calendar.py +195 -0
  415. bootstack/widgets/card.py +159 -0
  416. bootstack/widgets/carousel.py +241 -0
  417. bootstack/widgets/chart.py +302 -0
  418. bootstack/widgets/codeeditor.py +675 -0
  419. bootstack/widgets/contextmenu.py +371 -0
  420. bootstack/widgets/datatable.py +688 -0
  421. bootstack/widgets/datefield.py +395 -0
  422. bootstack/widgets/divider.py +60 -0
  423. bootstack/widgets/expander.py +579 -0
  424. bootstack/widgets/form.py +200 -0
  425. bootstack/widgets/gallery.py +250 -0
  426. bootstack/widgets/gauge.py +168 -0
  427. bootstack/widgets/grid.py +121 -0
  428. bootstack/widgets/groupbox.py +162 -0
  429. bootstack/widgets/label.py +229 -0
  430. bootstack/widgets/listview.py +354 -0
  431. bootstack/widgets/menubutton.py +419 -0
  432. bootstack/widgets/numberfield.py +431 -0
  433. bootstack/widgets/pagestack.py +345 -0
  434. bootstack/widgets/passwordfield.py +383 -0
  435. bootstack/widgets/pathfield.py +454 -0
  436. bootstack/widgets/picture.py +251 -0
  437. bootstack/widgets/progressbar.py +106 -0
  438. bootstack/widgets/radio_variants.py +271 -0
  439. bootstack/widgets/radiogroup.py +228 -0
  440. bootstack/widgets/scrollbar.py +64 -0
  441. bootstack/widgets/scrollview.py +186 -0
  442. bootstack/widgets/select.py +302 -0
  443. bootstack/widgets/selectbutton.py +182 -0
  444. bootstack/widgets/sidebar_toggle.py +130 -0
  445. bootstack/widgets/sizegrip.py +42 -0
  446. bootstack/widgets/slider.py +408 -0
  447. bootstack/widgets/spinbox.py +147 -0
  448. bootstack/widgets/spinnerfield.py +413 -0
  449. bootstack/widgets/splash.py +367 -0
  450. bootstack/widgets/splitview.py +482 -0
  451. bootstack/widgets/stacks.py +249 -0
  452. bootstack/widgets/statusbar.py +189 -0
  453. bootstack/widgets/tabs.py +425 -0
  454. bootstack/widgets/textarea.py +459 -0
  455. bootstack/widgets/textfield.py +410 -0
  456. bootstack/widgets/theme_toggle.py +92 -0
  457. bootstack/widgets/timefield.py +340 -0
  458. bootstack/widgets/toast.py +314 -0
  459. bootstack/widgets/togglegroup.py +231 -0
  460. bootstack/widgets/toolbar.py +347 -0
  461. bootstack/widgets/tooltip.py +94 -0
  462. bootstack/widgets/tree.py +648 -0
  463. bootstack/widgets/types.py +305 -0
  464. bootstack/widgets/window.py +307 -0
  465. bootstack-0.1.0.dist-info/METADATA +301 -0
  466. bootstack-0.1.0.dist-info/RECORD +471 -0
  467. bootstack-0.1.0.dist-info/WHEEL +5 -0
  468. bootstack-0.1.0.dist-info/entry_points.txt +2 -0
  469. bootstack-0.1.0.dist-info/licenses/LICENSE +21 -0
  470. bootstack-0.1.0.dist-info/licenses/NOTICE +10 -0
  471. bootstack-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,367 @@
1
+ from __future__ import annotations
2
+
3
+ import tkinter
4
+ from typing import TYPE_CHECKING, Any, Callable, Literal, overload
5
+
6
+ from bootstack.errors import BootstackError
7
+ from bootstack.events import Subscription
8
+ from bootstack.events._payloads import SplashDismissEvent
9
+ from bootstack.widgets._core.container import FlexContainer
10
+ from bootstack.widgets._core.events import register_widget_events
11
+ from bootstack.widgets._impl.primitives.flexframe import FlexFrame
12
+ from bootstack.widgets._impl.primitives.frame import Frame
13
+ from bootstack.widgets.types import Padding, SurfaceToken
14
+
15
+ if TYPE_CHECKING:
16
+ from bootstack.streams import Stream
17
+
18
+
19
+ # Fade ramp: ~250ms over 12 steps. Tuned for a soft, quick in/out that never
20
+ # feels like a stall; degrades to an instant snap where alpha isn't honored.
21
+ _FADE_STEPS = 12
22
+ _FADE_INTERVAL_MS = 20
23
+
24
+
25
+ class Splash(FlexContainer):
26
+ """A borderless app intro screen shown while the main window is built.
27
+
28
+ Constructing a `Splash` inside an `App` context registers it with that app
29
+ and shows it; the app then defers revealing its own window until the splash
30
+ dismisses. Author the splash's contents — a logo, a title, a status line —
31
+ inside its `with` block exactly as you would the app body::
32
+
33
+ with bs.App(title="My App") as app:
34
+ with bs.Splash(min_duration=1.0):
35
+ bs.Picture(logo)
36
+ bs.Label("My App", font="heading-lg")
37
+ bs.Label("Loading…", textsignal=status)
38
+ # ...build the heavy app body — the splash covers this cost...
39
+ app.run()
40
+
41
+ Where you write the `Splash` determines how much of startup it covers: put
42
+ it first to cover the most. The `with` block scopes content authoring only —
43
+ it does not bound the splash's lifetime, which is governed by `until`,
44
+ `min_duration`, `skippable`, and `dismiss()`.
45
+
46
+ Args:
47
+ until: What automatically closes the splash. `'ready'` (default) closes
48
+ it when the app finishes building. A number of seconds closes it
49
+ after that delay (app-ready does not auto-close it). `'manual'` never
50
+ auto-closes — use `skippable`, an authored button, or `dismiss()`.
51
+ skippable: When `True`, a click or the Escape key dismisses the splash.
52
+ min_duration: A floor in seconds — the splash never closes before this
53
+ has elapsed, even if its trigger fires sooner (prevents a blink on a
54
+ fast startup).
55
+ fade: Fade the window in and out where the platform supports window
56
+ alpha; snap instantly where it does not.
57
+ size: Fixed size as `(width, height)`. Defaults to auto-fitting the
58
+ content. Either way the splash is centered on screen.
59
+ surface: Surface token for the panel background.
60
+ padding: Inner content padding.
61
+ gap: Spacing between content items.
62
+ """
63
+
64
+ _auto_place = False # its own top-level window — no parent manages it
65
+
66
+ def __init__(
67
+ self,
68
+ *,
69
+ until: float | Literal["ready", "manual"] = "ready",
70
+ skippable: bool = False,
71
+ min_duration: float = 0.0,
72
+ fade: bool = True,
73
+ size: tuple[int, int] | None = None,
74
+ surface: SurfaceToken | str = "card",
75
+ padding: Padding = 24,
76
+ gap: int = 12,
77
+ ) -> None:
78
+ from bootstack._runtime.app import get_current_app
79
+ from bootstack._runtime.toplevel import Toplevel as _InternalToplevel
80
+
81
+ self._parent = None
82
+
83
+ # ----- Resolve & register on the ambient app -----
84
+ try:
85
+ app = get_current_app()
86
+ except RuntimeError:
87
+ app = None
88
+ if app is None:
89
+ raise BootstackError(
90
+ "Splash requires an App — construct it inside a "
91
+ "`with bs.App(...) as app:` block."
92
+ )
93
+ if getattr(app, "_splash", None) is not None:
94
+ raise BootstackError(
95
+ "An app can show only one Splash. A second Splash was "
96
+ "constructed before the first dismissed."
97
+ )
98
+ self._app = app
99
+ app._splash = self
100
+
101
+ # ----- Dismiss model -----
102
+ if isinstance(until, bool): # bool is an int subclass — reject explicitly
103
+ raise BootstackError(
104
+ f"Splash until= must be 'ready', 'manual', or a number of "
105
+ f"seconds; got {until!r}."
106
+ )
107
+ if isinstance(until, (int, float)):
108
+ self._until: str = "timer"
109
+ self._until_seconds: float | None = float(until)
110
+ elif until in ("ready", "manual"):
111
+ self._until = until
112
+ self._until_seconds = None
113
+ else:
114
+ raise BootstackError(
115
+ f"Splash until= must be 'ready', 'manual', or a number of "
116
+ f"seconds; got {until!r}."
117
+ )
118
+
119
+ self._skippable = skippable
120
+ self._min_duration = max(0.0, float(min_duration))
121
+ self._fade = fade
122
+ self._size = size
123
+
124
+ # ----- Lifecycle state -----
125
+ self._shown = False # _reveal() has run (idempotent guard)
126
+ self._is_showing = False # mapped and not yet dismissed
127
+ self._dismissing = False # _begin_dismiss() has run
128
+ self._min_elapsed = self._min_duration <= 0.0
129
+ self._pending_reason: str | None = None
130
+ self._app_reveal: Callable[[], Any] | None = None
131
+
132
+ # ----- Build the borderless top-level -----
133
+ # windowtype='splash' is the single cross-platform switch (#308):
134
+ # overrideredirect on Windows, MacWindowStyle on macOS, -type on X11.
135
+ # topmost keeps it above the (still-hidden) app window.
136
+ self._tk_toplevel = _InternalToplevel(
137
+ title="",
138
+ windowtype="splash",
139
+ overrideredirect=True,
140
+ topmost=True,
141
+ )
142
+ self._internal = self._tk_toplevel
143
+
144
+ # A 1px themed border frames the panel so it reads as an intentional
145
+ # surface rather than blending into a same-colored desktop.
146
+ self._region_root = Frame(self._tk_toplevel, show_border=True, padding=1)
147
+ self._region_root.pack(fill="both", expand=True)
148
+
149
+ # Content is centered both ways — the classic splash composition.
150
+ self._content_frame = FlexFrame(
151
+ self._region_root,
152
+ direction="vertical",
153
+ padding=padding,
154
+ gap=gap,
155
+ horizontal_items="center",
156
+ vertical_items="center",
157
+ surface=surface,
158
+ )
159
+ self._content_frame.pack(fill="both", expand=True)
160
+
161
+ if self._skippable:
162
+ self._tk_toplevel.bind("<Escape>", self._on_skip, add="+")
163
+ self._tk_toplevel.bind("<Button-1>", self._on_skip, add="+")
164
+
165
+ @property
166
+ def _flex_frame(self) -> Any:
167
+ return self._content_frame
168
+
169
+ # ----- Context manager: author content, then reveal -----------------------
170
+
171
+ def __exit__(self, exc_type, exc, tb) -> None:
172
+ super().__exit__(exc_type, exc, tb)
173
+ # Reveal AFTER the content is authored so centering uses the real size.
174
+ # Showing here (not at construction) means the splash is painted before
175
+ # the synchronous body build that follows the block — so it genuinely
176
+ # covers that cost.
177
+ if exc_type is None:
178
+ self._reveal()
179
+ return None
180
+
181
+ # ----- Public surface ------------------------------------------------------
182
+
183
+ @property
184
+ def is_showing(self) -> bool:
185
+ """Whether the splash is currently on screen."""
186
+ return self._is_showing
187
+
188
+ def dismiss(self) -> None:
189
+ """Dismiss the splash now, fading out and revealing the app.
190
+
191
+ Respects `min_duration` — if the floor has not elapsed, the dismissal is
192
+ deferred until it has. Safe to call more than once; later calls are
193
+ ignored once a dismissal is under way.
194
+ """
195
+ self._request_dismiss("manual")
196
+
197
+ @overload
198
+ def on_dismiss(self) -> "Stream": ...
199
+ @overload
200
+ def on_dismiss(self, handler: Callable[[SplashDismissEvent], Any]) -> Subscription: ...
201
+ def on_dismiss(
202
+ self,
203
+ handler: Callable[[SplashDismissEvent], Any] | None = None,
204
+ ) -> "Stream | Subscription":
205
+ """Register a callback fired when the splash begins dismissing.
206
+
207
+ The handler receives a :class:`~bootstack.events.SplashDismissEvent`
208
+ whose `reason` says why it closed (`'ready'`, `'timer'`, `'manual'`, or
209
+ `'skip'`). Fires once, as the fade-out starts.
210
+
211
+ Args:
212
+ handler: Called with the dismiss event. Omit to get a composable
213
+ :class:`~bootstack.streams.Stream`.
214
+
215
+ Returns:
216
+ A cancellable :class:`~bootstack.events.Subscription` when a handler
217
+ is given, otherwise a :class:`~bootstack.streams.Stream`.
218
+ """
219
+ return self.on("dismiss", handler)
220
+
221
+ # ----- App integration -----------------------------------------------------
222
+
223
+ def _notify_app_ready(self, reveal: Callable[[], Any]) -> None:
224
+ """Called by the app when it is built and ready to be revealed.
225
+
226
+ Stores the reveal callback so the splash can trigger it when it
227
+ dismisses. Under `until='ready'` this also kicks off the dismissal.
228
+ """
229
+ if not self._is_showing:
230
+ # Never shown (constructed without a `with` block) or already gone —
231
+ # don't strand the app; reveal it now and drop any orphan splash.
232
+ self._app_reveal = None
233
+ self._clear_registration()
234
+ try:
235
+ self._tk_toplevel.destroy()
236
+ except tkinter.TclError:
237
+ pass
238
+ reveal()
239
+ return
240
+ self._app_reveal = reveal
241
+ if self._until == "ready":
242
+ self._request_dismiss("ready")
243
+
244
+ # ----- Reveal --------------------------------------------------------------
245
+
246
+ def _reveal(self) -> None:
247
+ if self._shown:
248
+ return
249
+ self._shown = True
250
+ top = self._tk_toplevel
251
+ top.update_idletasks()
252
+
253
+ if self._size is not None:
254
+ top.geometry(f"{int(self._size[0])}x{int(self._size[1])}")
255
+ top.update_idletasks()
256
+
257
+ from bootstack._runtime.window_utilities import WindowPositioning
258
+
259
+ x, y = WindowPositioning.center_on_screen(top)
260
+ x, y = WindowPositioning.ensure_on_screen(top, x, y)
261
+ top.geometry(f"+{x}+{y}")
262
+
263
+ if self._fade:
264
+ try:
265
+ top.attributes("-alpha", 0.0)
266
+ except tkinter.TclError:
267
+ self._fade = False
268
+
269
+ top.deiconify()
270
+ top.lift()
271
+ try:
272
+ top.focus_set()
273
+ except tkinter.TclError:
274
+ pass
275
+ # Force a paint now so the splash is on screen before the synchronous
276
+ # body build that follows the `with` block.
277
+ top.update()
278
+ self._is_showing = True
279
+
280
+ if self._fade:
281
+ self._fade_in(1)
282
+ self._start_timers()
283
+
284
+ def _start_timers(self) -> None:
285
+ top = self._tk_toplevel
286
+ if self._min_duration > 0:
287
+ top.after(int(self._min_duration * 1000), self._on_min_elapsed)
288
+ if self._until_seconds is not None:
289
+ top.after(int(self._until_seconds * 1000),
290
+ lambda: self._request_dismiss("timer"))
291
+
292
+ # ----- Fade ramps ----------------------------------------------------------
293
+
294
+ def _fade_in(self, step: int) -> None:
295
+ if not self._is_showing or self._dismissing:
296
+ return
297
+ alpha = min(1.0, step / _FADE_STEPS)
298
+ try:
299
+ self._tk_toplevel.attributes("-alpha", alpha)
300
+ except tkinter.TclError:
301
+ return
302
+ if step < _FADE_STEPS:
303
+ self._tk_toplevel.after(_FADE_INTERVAL_MS, lambda: self._fade_in(step + 1))
304
+
305
+ def _fade_out(self, step: int) -> None:
306
+ alpha = max(0.0, 1.0 - step / _FADE_STEPS)
307
+ try:
308
+ self._tk_toplevel.attributes("-alpha", alpha)
309
+ except tkinter.TclError:
310
+ self._finalize()
311
+ return
312
+ if step < _FADE_STEPS:
313
+ self._tk_toplevel.after(_FADE_INTERVAL_MS, lambda: self._fade_out(step + 1))
314
+ else:
315
+ self._finalize()
316
+
317
+ # ----- Dismiss flow --------------------------------------------------------
318
+
319
+ def _on_skip(self, _event: Any = None) -> None:
320
+ self._request_dismiss("skip")
321
+
322
+ def _on_min_elapsed(self) -> None:
323
+ self._min_elapsed = True
324
+ if self._pending_reason is not None:
325
+ self._begin_dismiss(self._pending_reason)
326
+
327
+ def _request_dismiss(self, reason: str) -> None:
328
+ if self._dismissing or not self._is_showing:
329
+ return
330
+ if not self._min_elapsed:
331
+ # Hold the first requested reason until the floor passes.
332
+ if self._pending_reason is None:
333
+ self._pending_reason = reason
334
+ return
335
+ self._begin_dismiss(reason)
336
+
337
+ def _begin_dismiss(self, reason: str) -> None:
338
+ if self._dismissing:
339
+ return
340
+ self._dismissing = True
341
+ self.emit("dismiss", data=SplashDismissEvent(reason=reason)) # type: ignore[arg-type]
342
+ # Reveal the app now so it is painted behind the (topmost) fading splash.
343
+ if self._app_reveal is not None:
344
+ reveal, self._app_reveal = self._app_reveal, None
345
+ try:
346
+ reveal()
347
+ except Exception:
348
+ pass
349
+ if self._fade and self._is_showing:
350
+ self._fade_out(1)
351
+ else:
352
+ self._finalize()
353
+
354
+ def _finalize(self) -> None:
355
+ self._is_showing = False
356
+ self._clear_registration()
357
+ try:
358
+ self._tk_toplevel.destroy()
359
+ except tkinter.TclError:
360
+ pass
361
+
362
+ def _clear_registration(self) -> None:
363
+ if getattr(self._app, "_splash", None) is self:
364
+ self._app._splash = None
365
+
366
+
367
+ register_widget_events(Splash, {"dismiss": "<<SplashDismiss>>"})