bootstack 0.1.0a1__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 (419) hide show
  1. bootstack/__init__.py +249 -0
  2. bootstack/__main__.py +5 -0
  3. bootstack/api/__init__.py +127 -0
  4. bootstack/api/app.py +30 -0
  5. bootstack/api/constants.py +3 -0
  6. bootstack/api/data.py +23 -0
  7. bootstack/api/dialogs.py +44 -0
  8. bootstack/api/i18n.py +17 -0
  9. bootstack/api/localization.py +16 -0
  10. bootstack/api/menu.py +7 -0
  11. bootstack/api/style.py +23 -0
  12. bootstack/api/utils.py +24 -0
  13. bootstack/api/widgets.py +137 -0
  14. bootstack/assets/__init__.py +24 -0
  15. bootstack/assets/bootstack-transparent.png +0 -0
  16. bootstack/assets/bootstack.ico +0 -0
  17. bootstack/assets/bootstack.png +0 -0
  18. bootstack/assets/elements/__init__.py +0 -0
  19. bootstack/assets/elements/badge-pill.png +0 -0
  20. bootstack/assets/elements/badge-square.png +0 -0
  21. bootstack/assets/elements/border.png +0 -0
  22. bootstack/assets/elements/button-compact.png +0 -0
  23. bootstack/assets/elements/button-default.png +0 -0
  24. bootstack/assets/elements/button-group-horizontal-after-compact.png +0 -0
  25. bootstack/assets/elements/button-group-horizontal-after-default.png +0 -0
  26. bootstack/assets/elements/button-group-horizontal-before-compact.png +0 -0
  27. bootstack/assets/elements/button-group-horizontal-before-default.png +0 -0
  28. bootstack/assets/elements/button-group-horizontal-center-compact.png +0 -0
  29. bootstack/assets/elements/button-group-horizontal-center-default.png +0 -0
  30. bootstack/assets/elements/button-group-vertical-after-compact.png +0 -0
  31. bootstack/assets/elements/button-group-vertical-after-default.png +0 -0
  32. bootstack/assets/elements/button-group-vertical-before-compact.png +0 -0
  33. bootstack/assets/elements/button-group-vertical-before-default.png +0 -0
  34. bootstack/assets/elements/button-group-vertical-center-compact.png +0 -0
  35. bootstack/assets/elements/button-group-vertical-center-default.png +0 -0
  36. bootstack/assets/elements/checkbox-checked.png +0 -0
  37. bootstack/assets/elements/checkbox-indeterminate.png +0 -0
  38. bootstack/assets/elements/checkbox-unchecked.png +0 -0
  39. bootstack/assets/elements/field.png +0 -0
  40. bootstack/assets/elements/input-after-compact.png +0 -0
  41. bootstack/assets/elements/input-after-default.png +0 -0
  42. bootstack/assets/elements/input-before-compact.png +0 -0
  43. bootstack/assets/elements/input-before-default.png +0 -0
  44. bootstack/assets/elements/input-compact.png +0 -0
  45. bootstack/assets/elements/input-default.png +0 -0
  46. bootstack/assets/elements/list-item-separated.png +0 -0
  47. bootstack/assets/elements/list-item.png +0 -0
  48. bootstack/assets/elements/manifest.toml +480 -0
  49. bootstack/assets/elements/menu-item.png +0 -0
  50. bootstack/assets/elements/nav-button-compact.png +0 -0
  51. bootstack/assets/elements/nav-button-default.png +0 -0
  52. bootstack/assets/elements/nav-icon-button-compact.png +0 -0
  53. bootstack/assets/elements/nav-icon-button-default.png +0 -0
  54. bootstack/assets/elements/notebook-client-border.png +0 -0
  55. bootstack/assets/elements/notebook-tab-active.png +0 -0
  56. bootstack/assets/elements/notebook-tab-bar.png +0 -0
  57. bootstack/assets/elements/notebook-tab-normal.png +0 -0
  58. bootstack/assets/elements/notebook-tab-pill.png +0 -0
  59. bootstack/assets/elements/progress-bar-horizontal-striped.png +0 -0
  60. bootstack/assets/elements/progress-bar-solid.png +0 -0
  61. bootstack/assets/elements/progress-bar-thin.png +0 -0
  62. bootstack/assets/elements/progress-bar-vertical-striped.png +0 -0
  63. bootstack/assets/elements/radio-selected.png +0 -0
  64. bootstack/assets/elements/radio-unselected.png +0 -0
  65. bootstack/assets/elements/scrollbar-horizontal.png +0 -0
  66. bootstack/assets/elements/scrollbar-vertical.png +0 -0
  67. bootstack/assets/elements/slider-handle-focus.png +0 -0
  68. bootstack/assets/elements/slider-handle.png +0 -0
  69. bootstack/assets/elements/slider-track-horizontal.png +0 -0
  70. bootstack/assets/elements/slider-track-vertical.png +0 -0
  71. bootstack/assets/elements/switch-off.png +0 -0
  72. bootstack/assets/elements/switch-on.png +0 -0
  73. bootstack/assets/elements/tabs-bar-horizontal.png +0 -0
  74. bootstack/assets/elements/tabs-bar-vertical.png +0 -0
  75. bootstack/assets/elements/tabs-pill.png +0 -0
  76. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
  77. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +853 -0
  78. bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +875 -0
  79. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
  80. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +853 -0
  81. bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
  82. bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +853 -0
  83. bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
  84. bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +853 -0
  85. bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
  86. bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +875 -0
  87. bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
  88. bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +853 -0
  89. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
  90. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +853 -0
  91. bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
  92. bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +851 -0
  93. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
  94. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +842 -0
  95. bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
  96. bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +841 -0
  97. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
  98. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +914 -0
  99. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
  100. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +842 -0
  101. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
  102. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +841 -0
  103. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
  104. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +841 -0
  105. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
  106. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +842 -0
  107. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
  108. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +842 -0
  109. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
  110. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +842 -0
  111. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
  112. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +842 -0
  113. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
  114. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +842 -0
  115. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
  116. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +842 -0
  117. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
  118. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +842 -0
  119. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
  120. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +842 -0
  121. bootstack/assets/themes/__init__.py +0 -0
  122. bootstack/assets/themes/amber-dark.json +32 -0
  123. bootstack/assets/themes/amber-light.json +32 -0
  124. bootstack/assets/themes/aurora-dark.json +32 -0
  125. bootstack/assets/themes/aurora-light.json +32 -0
  126. bootstack/assets/themes/bootstrap-dark.json +32 -0
  127. bootstack/assets/themes/bootstrap-light.json +32 -0
  128. bootstack/assets/themes/classic-dark.json +32 -0
  129. bootstack/assets/themes/classic-light.json +32 -0
  130. bootstack/assets/themes/docs-dark.json +32 -0
  131. bootstack/assets/themes/docs-light.json +32 -0
  132. bootstack/assets/themes/forest-dark.json +32 -0
  133. bootstack/assets/themes/forest-light.json +32 -0
  134. bootstack/assets/themes/ocean-dark.json +32 -0
  135. bootstack/assets/themes/ocean-light.json +32 -0
  136. bootstack/assets/themes/rose-dark.json +32 -0
  137. bootstack/assets/themes/rose-light.json +32 -0
  138. bootstack/assets/widgets/__init__.py +0 -0
  139. bootstack/assets/widgets/badge-default.png +0 -0
  140. bootstack/assets/widgets/badge-pill.png +0 -0
  141. bootstack/assets/widgets/border.png +0 -0
  142. bootstack/assets/widgets/button-group-horizontal-after.png +0 -0
  143. bootstack/assets/widgets/button-group-horizontal-before.png +0 -0
  144. bootstack/assets/widgets/button-group-horizontal-center.png +0 -0
  145. bootstack/assets/widgets/button-group-vertical-after.png +0 -0
  146. bootstack/assets/widgets/button-group-vertical-before.png +0 -0
  147. bootstack/assets/widgets/button-group-vertical-center.png +0 -0
  148. bootstack/assets/widgets/button.png +0 -0
  149. bootstack/assets/widgets/checkbox-checked.png +0 -0
  150. bootstack/assets/widgets/checkbox-indeterminate.png +0 -0
  151. bootstack/assets/widgets/checkbox-unchecked.png +0 -0
  152. bootstack/assets/widgets/field.png +0 -0
  153. bootstack/assets/widgets/icon-button.png +0 -0
  154. bootstack/assets/widgets/input-inner.png +0 -0
  155. bootstack/assets/widgets/input-prefix.png +0 -0
  156. bootstack/assets/widgets/input-suffix.png +0 -0
  157. bootstack/assets/widgets/input.png +0 -0
  158. bootstack/assets/widgets/list-item-focus.png +0 -0
  159. bootstack/assets/widgets/list-item-separated.png +0 -0
  160. bootstack/assets/widgets/menu-item-separated.png +0 -0
  161. bootstack/assets/widgets/notebook-client-border.png +0 -0
  162. bootstack/assets/widgets/notebook-pill-active.png +0 -0
  163. bootstack/assets/widgets/notebook-pill-inactive.png +0 -0
  164. bootstack/assets/widgets/notebook-tab-active.png +0 -0
  165. bootstack/assets/widgets/notebook-tab-border.png +0 -0
  166. bootstack/assets/widgets/notebook-tab-normal.png +0 -0
  167. bootstack/assets/widgets/notebook-underline.png +0 -0
  168. bootstack/assets/widgets/progress-bar-horizontal-default.png +0 -0
  169. bootstack/assets/widgets/progress-bar-horizontal-striped.png +0 -0
  170. bootstack/assets/widgets/progress-bar-vertical-default.png +0 -0
  171. bootstack/assets/widgets/progress-bar-vertical-striped.png +0 -0
  172. bootstack/assets/widgets/progress-trough-horizontal.png +0 -0
  173. bootstack/assets/widgets/progress-trough-vertical.png +0 -0
  174. bootstack/assets/widgets/radio-selected.png +0 -0
  175. bootstack/assets/widgets/radio-unselected.png +0 -0
  176. bootstack/assets/widgets/scrollbar-horizontal-rounded.png +0 -0
  177. bootstack/assets/widgets/scrollbar-vertical-rounded.png +0 -0
  178. bootstack/assets/widgets/separator-horizontal.png +0 -0
  179. bootstack/assets/widgets/separator-vertical.png +0 -0
  180. bootstack/assets/widgets/slider-handle-focus.png +0 -0
  181. bootstack/assets/widgets/slider-handle.png +0 -0
  182. bootstack/assets/widgets/slider-track-horizontal.png +0 -0
  183. bootstack/assets/widgets/slider-track-vertical.png +0 -0
  184. bootstack/assets/widgets/switch-off.png +0 -0
  185. bootstack/assets/widgets/switch-on.png +0 -0
  186. bootstack/assets/widgets/tabs-bar-horizontal.png +0 -0
  187. bootstack/assets/widgets/tabs-bar-vertical.png +0 -0
  188. bootstack/assets/widgets/tabs-pill.png +0 -0
  189. bootstack/cli/__init__.py +124 -0
  190. bootstack/cli/__main__.py +6 -0
  191. bootstack/cli/add.py +439 -0
  192. bootstack/cli/build.py +115 -0
  193. bootstack/cli/config.py +287 -0
  194. bootstack/cli/demo.py +1267 -0
  195. bootstack/cli/doctor.py +195 -0
  196. bootstack/cli/list_cmd.py +71 -0
  197. bootstack/cli/promote.py +120 -0
  198. bootstack/cli/pyinstaller.py +246 -0
  199. bootstack/cli/run.py +99 -0
  200. bootstack/cli/start.py +105 -0
  201. bootstack/cli/templates/__init__.py +861 -0
  202. bootstack/constants.py +325 -0
  203. bootstack/core/__init__.py +34 -0
  204. bootstack/core/capabilities/__init__.py +45 -0
  205. bootstack/core/capabilities/after.py +103 -0
  206. bootstack/core/capabilities/bind.py +154 -0
  207. bootstack/core/capabilities/bindtags.py +112 -0
  208. bootstack/core/capabilities/busy.py +61 -0
  209. bootstack/core/capabilities/clipboard.py +88 -0
  210. bootstack/core/capabilities/focus.py +118 -0
  211. bootstack/core/capabilities/grab.py +65 -0
  212. bootstack/core/capabilities/grid.py +188 -0
  213. bootstack/core/capabilities/localization.py +231 -0
  214. bootstack/core/capabilities/pack.py +119 -0
  215. bootstack/core/capabilities/place.py +92 -0
  216. bootstack/core/capabilities/selection.py +136 -0
  217. bootstack/core/capabilities/signals.py +242 -0
  218. bootstack/core/capabilities/winfo.py +315 -0
  219. bootstack/core/colorutils.py +234 -0
  220. bootstack/core/exceptions.py +95 -0
  221. bootstack/core/images.py +283 -0
  222. bootstack/core/localization/README.md +90 -0
  223. bootstack/core/localization/__init__.py +13 -0
  224. bootstack/core/localization/intl_format.py +580 -0
  225. bootstack/core/localization/msgcat.py +425 -0
  226. bootstack/core/localization/specs.py +143 -0
  227. bootstack/core/mixins/__init__.py +1 -0
  228. bootstack/core/mixins/ttk_state.py +35 -0
  229. bootstack/core/mixins/widget.py +132 -0
  230. bootstack/core/publisher.py +147 -0
  231. bootstack/core/signals/README.md +112 -0
  232. bootstack/core/signals/__init__.py +8 -0
  233. bootstack/core/signals/integration.py +100 -0
  234. bootstack/core/signals/signal.py +317 -0
  235. bootstack/core/signals/types.py +4 -0
  236. bootstack/core/validation/__init__.py +5 -0
  237. bootstack/core/validation/types.py +13 -0
  238. bootstack/core/validation/validation_result.py +17 -0
  239. bootstack/core/validation/validation_rules.py +112 -0
  240. bootstack/core/variables.py +62 -0
  241. bootstack/datasource/README.md +607 -0
  242. bootstack/datasource/__init__.py +51 -0
  243. bootstack/datasource/base.py +474 -0
  244. bootstack/datasource/file_source.py +541 -0
  245. bootstack/datasource/memory_source.py +482 -0
  246. bootstack/datasource/sqlite_source.py +453 -0
  247. bootstack/datasource/types.py +259 -0
  248. bootstack/dialogs/__init__.py +56 -0
  249. bootstack/dialogs/colorchooser.py +674 -0
  250. bootstack/dialogs/colordropper.py +257 -0
  251. bootstack/dialogs/datedialog.py +404 -0
  252. bootstack/dialogs/dialog.py +514 -0
  253. bootstack/dialogs/filterdialog.py +358 -0
  254. bootstack/dialogs/fontdialog.py +339 -0
  255. bootstack/dialogs/formdialog.py +541 -0
  256. bootstack/dialogs/message.py +489 -0
  257. bootstack/dialogs/query.py +561 -0
  258. bootstack/py.typed +1 -0
  259. bootstack/runtime/__init__.py +3 -0
  260. bootstack/runtime/app.py +879 -0
  261. bootstack/runtime/base_window.py +786 -0
  262. bootstack/runtime/events.py +399 -0
  263. bootstack/runtime/menu.py +510 -0
  264. bootstack/runtime/shortcuts.py +423 -0
  265. bootstack/runtime/tk_patch.py +31 -0
  266. bootstack/runtime/toplevel.py +131 -0
  267. bootstack/runtime/utility.py +371 -0
  268. bootstack/runtime/visual_focus.py +228 -0
  269. bootstack/runtime/window_utilities.py +1043 -0
  270. bootstack/style/__init__.py +5498 -0
  271. bootstack/style/bootstyle.py +507 -0
  272. bootstack/style/bootstyle_builder_base.py +752 -0
  273. bootstack/style/bootstyle_builder_mixed.py +93 -0
  274. bootstack/style/bootstyle_builder_tk.py +109 -0
  275. bootstack/style/bootstyle_builder_ttk.py +354 -0
  276. bootstack/style/builders/__init__.py +51 -0
  277. bootstack/style/builders/badge.py +44 -0
  278. bootstack/style/builders/button.py +453 -0
  279. bootstack/style/builders/buttongroup.py +344 -0
  280. bootstack/style/builders/calendar.py +271 -0
  281. bootstack/style/builders/checkbutton.py +95 -0
  282. bootstack/style/builders/combobox.py +112 -0
  283. bootstack/style/builders/contextmenu.py +268 -0
  284. bootstack/style/builders/entry.py +83 -0
  285. bootstack/style/builders/expander.py +171 -0
  286. bootstack/style/builders/field.py +312 -0
  287. bootstack/style/builders/frame.py +27 -0
  288. bootstack/style/builders/label.py +28 -0
  289. bootstack/style/builders/labelframe.py +41 -0
  290. bootstack/style/builders/listview.py +267 -0
  291. bootstack/style/builders/menubar.py +74 -0
  292. bootstack/style/builders/menubutton.py +408 -0
  293. bootstack/style/builders/notebook.py +316 -0
  294. bootstack/style/builders/panedwindow.py +25 -0
  295. bootstack/style/builders/progressbar.py +71 -0
  296. bootstack/style/builders/radiobutton.py +68 -0
  297. bootstack/style/builders/scale.py +66 -0
  298. bootstack/style/builders/scrollbar.py +360 -0
  299. bootstack/style/builders/separator.py +45 -0
  300. bootstack/style/builders/sidenav.py +313 -0
  301. bootstack/style/builders/sizegrip.py +15 -0
  302. bootstack/style/builders/spinbox.py +119 -0
  303. bootstack/style/builders/switch.py +67 -0
  304. bootstack/style/builders/tabitem.py +205 -0
  305. bootstack/style/builders/toolbutton.py +260 -0
  306. bootstack/style/builders/tooltip.py +26 -0
  307. bootstack/style/builders/treeview.py +269 -0
  308. bootstack/style/builders/utils.py +404 -0
  309. bootstack/style/builders_tk/__init__.py +16 -0
  310. bootstack/style/builders_tk/defaults.py +229 -0
  311. bootstack/style/element.py +173 -0
  312. bootstack/style/style.py +499 -0
  313. bootstack/style/theme_provider.py +449 -0
  314. bootstack/style/tk_patch.py +5 -0
  315. bootstack/style/token_maps.py +42 -0
  316. bootstack/style/types.py +32 -0
  317. bootstack/style/typography.py +527 -0
  318. bootstack/style/utility.py +696 -0
  319. bootstack/themes/__init__.py +12 -0
  320. bootstack/themes/standard.py +415 -0
  321. bootstack/themes/user.py +45 -0
  322. bootstack/widgets/__init__.py +53 -0
  323. bootstack/widgets/composites/__init__.py +38 -0
  324. bootstack/widgets/composites/accordion.py +385 -0
  325. bootstack/widgets/composites/appshell.py +445 -0
  326. bootstack/widgets/composites/buttongroup.py +391 -0
  327. bootstack/widgets/composites/calendar.py +914 -0
  328. bootstack/widgets/composites/compositeframe.py +282 -0
  329. bootstack/widgets/composites/contextmenu.py +1754 -0
  330. bootstack/widgets/composites/dateentry.py +261 -0
  331. bootstack/widgets/composites/dropdownbutton.py +190 -0
  332. bootstack/widgets/composites/expander.py +508 -0
  333. bootstack/widgets/composites/field.py +448 -0
  334. bootstack/widgets/composites/floodgauge.py +434 -0
  335. bootstack/widgets/composites/form.py +983 -0
  336. bootstack/widgets/composites/labeledscale.py +209 -0
  337. bootstack/widgets/composites/list/__init__.py +15 -0
  338. bootstack/widgets/composites/list/listitem.py +733 -0
  339. bootstack/widgets/composites/list/listview.py +1507 -0
  340. bootstack/widgets/composites/menubar.py +303 -0
  341. bootstack/widgets/composites/meter.py +882 -0
  342. bootstack/widgets/composites/numericentry.py +183 -0
  343. bootstack/widgets/composites/pagestack.py +330 -0
  344. bootstack/widgets/composites/passwordentry.py +149 -0
  345. bootstack/widgets/composites/pathentry.py +223 -0
  346. bootstack/widgets/composites/radiogroup.py +466 -0
  347. bootstack/widgets/composites/scrolledtext.py +388 -0
  348. bootstack/widgets/composites/scrolledtext.pyi +186 -0
  349. bootstack/widgets/composites/scrollview.py +675 -0
  350. bootstack/widgets/composites/selectbox.py +544 -0
  351. bootstack/widgets/composites/sidenav/__init__.py +24 -0
  352. bootstack/widgets/composites/sidenav/group.py +485 -0
  353. bootstack/widgets/composites/sidenav/header.py +83 -0
  354. bootstack/widgets/composites/sidenav/item.py +413 -0
  355. bootstack/widgets/composites/sidenav/separator.py +51 -0
  356. bootstack/widgets/composites/sidenav/view.py +919 -0
  357. bootstack/widgets/composites/spinnerentry.py +232 -0
  358. bootstack/widgets/composites/tableview/__init__.py +5 -0
  359. bootstack/widgets/composites/tableview/tableview.py +2254 -0
  360. bootstack/widgets/composites/tableview/types.py +169 -0
  361. bootstack/widgets/composites/tabs/__init__.py +6 -0
  362. bootstack/widgets/composites/tabs/tabitem.py +372 -0
  363. bootstack/widgets/composites/tabs/tabs.py +478 -0
  364. bootstack/widgets/composites/tabs/tabview.py +352 -0
  365. bootstack/widgets/composites/textentry.py +90 -0
  366. bootstack/widgets/composites/timeentry.py +189 -0
  367. bootstack/widgets/composites/toast.py +364 -0
  368. bootstack/widgets/composites/togglegroup.py +382 -0
  369. bootstack/widgets/composites/toolbar.py +393 -0
  370. bootstack/widgets/composites/tooltip.py +404 -0
  371. bootstack/widgets/internal/__init__.py +0 -0
  372. bootstack/widgets/internal/wrapper_base.py +304 -0
  373. bootstack/widgets/mixins/__init__.py +25 -0
  374. bootstack/widgets/mixins/configure_mixin.py +186 -0
  375. bootstack/widgets/mixins/entry_mixin.py +70 -0
  376. bootstack/widgets/mixins/font_mixin.py +346 -0
  377. bootstack/widgets/mixins/icon_mixin.py +38 -0
  378. bootstack/widgets/mixins/localization_mixin.py +255 -0
  379. bootstack/widgets/mixins/signal_mixin.py +272 -0
  380. bootstack/widgets/mixins/validation_mixin.py +204 -0
  381. bootstack/widgets/parts/__init__.py +11 -0
  382. bootstack/widgets/parts/numberentry_part.py +345 -0
  383. bootstack/widgets/parts/spinnerentry_part.py +394 -0
  384. bootstack/widgets/parts/textentry_part.py +344 -0
  385. bootstack/widgets/primitives/__init__.py +55 -0
  386. bootstack/widgets/primitives/badge.py +44 -0
  387. bootstack/widgets/primitives/button.py +89 -0
  388. bootstack/widgets/primitives/card.py +66 -0
  389. bootstack/widgets/primitives/checkbutton.py +124 -0
  390. bootstack/widgets/primitives/checktoggle.py +53 -0
  391. bootstack/widgets/primitives/combobox.py +165 -0
  392. bootstack/widgets/primitives/entry.py +98 -0
  393. bootstack/widgets/primitives/frame.py +206 -0
  394. bootstack/widgets/primitives/gridframe.py +479 -0
  395. bootstack/widgets/primitives/label.py +95 -0
  396. bootstack/widgets/primitives/labelframe.py +63 -0
  397. bootstack/widgets/primitives/menubutton.py +118 -0
  398. bootstack/widgets/primitives/notebook.py +551 -0
  399. bootstack/widgets/primitives/optionmenu.py +248 -0
  400. bootstack/widgets/primitives/packframe.py +228 -0
  401. bootstack/widgets/primitives/panedwindow.py +58 -0
  402. bootstack/widgets/primitives/progressbar.py +95 -0
  403. bootstack/widgets/primitives/radiobutton.py +115 -0
  404. bootstack/widgets/primitives/radiotoggle.py +50 -0
  405. bootstack/widgets/primitives/scale.py +85 -0
  406. bootstack/widgets/primitives/scrollbar.py +56 -0
  407. bootstack/widgets/primitives/separator.py +56 -0
  408. bootstack/widgets/primitives/sizegrip.py +47 -0
  409. bootstack/widgets/primitives/spinbox.py +91 -0
  410. bootstack/widgets/primitives/switch.py +41 -0
  411. bootstack/widgets/primitives/treeview.py +77 -0
  412. bootstack/widgets/types.py +20 -0
  413. bootstack-0.1.0a1.dist-info/METADATA +196 -0
  414. bootstack-0.1.0a1.dist-info/RECORD +419 -0
  415. bootstack-0.1.0a1.dist-info/WHEEL +5 -0
  416. bootstack-0.1.0a1.dist-info/entry_points.txt +2 -0
  417. bootstack-0.1.0a1.dist-info/licenses/LICENSE +22 -0
  418. bootstack-0.1.0a1.dist-info/licenses/NOTICE +10 -0
  419. bootstack-0.1.0a1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,385 @@
1
+ """Accordion widget - a container of mutually exclusive expanders."""
2
+ from __future__ import annotations
3
+
4
+ from typing import Any, Callable, Literal, TYPE_CHECKING
5
+
6
+ from bootstack.widgets.primitives.frame import Frame
7
+ from bootstack.widgets.primitives.separator import Separator
8
+ from bootstack.widgets.composites.expander import Expander
9
+ from bootstack.widgets.mixins import configure_delegate
10
+ from bootstack.widgets.types import Master
11
+
12
+ if TYPE_CHECKING:
13
+ pass
14
+
15
+
16
+ class Accordion(Frame):
17
+ """A container of Expander widgets with optional mutual exclusion.
18
+
19
+ The Accordion manages a group of Expanders, optionally enforcing that only
20
+ one can be expanded at a time. When `allow_multiple=False`, expanding one
21
+ section automatically collapses the others. When `allow_collapse_all=False`,
22
+ at least one section must remain open.
23
+
24
+ Attributes:
25
+ expanders (list[Expander]): List of managed Expander widgets.
26
+ expanded (list[Expander]): Currently expanded Expander(s).
27
+
28
+ !!! note "Events"
29
+ - `<<AccordionChange>>`: Fired when the expanded section(s) change.
30
+ `event.data = {'expanded': list[Expander]}`
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ master: Master = None,
36
+ *,
37
+ allow_multiple: bool = False,
38
+ allow_collapse_all: bool = True,
39
+ show_separators: bool = False,
40
+ accent: str = None,
41
+ variant: str = None,
42
+ **kwargs
43
+ ):
44
+ """Create an Accordion widget.
45
+
46
+ Args:
47
+ master (Master): Parent widget. If None, uses the default root window.
48
+ allow_multiple (bool): If True, multiple sections can be open at once.
49
+ If False (default), only one section can be open at a time.
50
+ allow_collapse_all (bool): If True (default), all sections can be collapsed.
51
+ If False, at least one section must remain open.
52
+ show_separators (bool): If True, show separators between expanders.
53
+ accent (str): Accent token for the expanders (e.g., 'success', 'primary').
54
+ variant (str): Variant for the expanders (e.g., 'solid', 'default').
55
+ **kwargs: Additional arguments passed to Frame.
56
+ """
57
+
58
+ if 'show_border' in kwargs:
59
+ kwargs.setdefault('padding', 3) # required to avoid clipping corners
60
+
61
+ super().__init__(master, **kwargs)
62
+
63
+ self._allow_multiple = allow_multiple
64
+ self._allow_collapse_all = allow_collapse_all
65
+ self._show_separators = show_separators
66
+ self._accent = accent
67
+ self._variant = variant
68
+ self._expanders: dict[str, Expander] = {}
69
+ self._expander_order: list[str] = []
70
+ self._separator_widgets: list[Separator] = []
71
+ self._updating = False # Prevent recursive updates
72
+ self._counter = 0 # For auto-generating keys
73
+
74
+ def add(
75
+ self,
76
+ expander: Expander = None,
77
+ *,
78
+ key: str = None,
79
+ title: str = "",
80
+ icon: str | dict = None,
81
+ expanded: bool = None,
82
+ **kwargs
83
+ ) -> Expander:
84
+ """Add an expander to the accordion.
85
+
86
+ Args:
87
+ expander (Expander | None): Existing Expander to add. If None, creates one.
88
+ key (str | None): Unique identifier for the expander. Auto-generated if not provided.
89
+ title (str): Title for the expander header (when creating new).
90
+ icon (str | dict): Icon for the expander header (when creating new).
91
+ expanded (bool | None): Initial expansion state. If None, first expander
92
+ is expanded when allow_collapse_all=False, otherwise collapsed.
93
+ **kwargs: When expander is None, passed to Expander constructor.
94
+
95
+ Returns:
96
+ Expander: The added or created Expander widget.
97
+
98
+ Raises:
99
+ ValueError: If an expander with the same key already exists.
100
+ """
101
+ # Auto-generate key if not provided
102
+ if key is None:
103
+ key = f"expander_{self._counter}"
104
+ self._counter += 1
105
+
106
+ if key in self._expanders:
107
+ raise ValueError(f"An expander with the key '{key}' already exists.")
108
+
109
+ # Add separator before this expander (if not the first)
110
+ if self._show_separators and len(self._expanders) > 0:
111
+ sep = Separator(self, orient='horizontal')
112
+ sep.pack(fill='x')
113
+ self._separator_widgets.append(sep)
114
+
115
+ # Create expander if not provided
116
+ if expander is None:
117
+ # Determine initial expanded state
118
+ if expanded is None:
119
+ # If not collapsible and this is the first, expand it
120
+ if not self._allow_collapse_all and len(self._expanders) == 0:
121
+ expanded = True
122
+ else:
123
+ expanded = False
124
+
125
+ # Get accent/variant from kwargs or use accordion defaults
126
+ accent = self._accent or kwargs.pop('accent', None)
127
+ variant = self._variant or kwargs.pop('variant', None)
128
+
129
+ expander = Expander(
130
+ self,
131
+ title=title,
132
+ icon=icon,
133
+ expanded=expanded,
134
+ highlight=True,
135
+ accent=accent,
136
+ variant=variant,
137
+ **kwargs
138
+ )
139
+ else:
140
+ # Configure existing expander
141
+ expander.configure(highlight=True)
142
+ if expanded is not None:
143
+ if expanded:
144
+ expander.expand()
145
+ else:
146
+ expander.collapse()
147
+
148
+ expander.pack(fill='x')
149
+ self._expanders[key] = expander
150
+ self._expander_order.append(key)
151
+
152
+ # Bind to toggle events
153
+ expander.on_toggled(lambda e, exp=expander: self._on_expander_toggle(exp, e))
154
+
155
+ return expander
156
+
157
+ def remove(self, key: str) -> None:
158
+ """Remove an expander from the accordion.
159
+
160
+ Args:
161
+ key: The key of the expander to remove.
162
+
163
+ Raises:
164
+ KeyError: If no expander with the given key exists.
165
+
166
+ Note:
167
+ The expander widget is destroyed. If allow_collapse_all=False and
168
+ removing would leave no expanders, or would remove the only
169
+ open expander, another expander will be expanded automatically.
170
+ """
171
+ if key not in self._expanders:
172
+ raise KeyError(f"No expander with key '{key}'")
173
+
174
+ expander = self._expanders[key]
175
+ index = self._expander_order.index(key)
176
+ was_expanded = expander['expanded']
177
+
178
+ # Remove associated separator
179
+ if self._show_separators and self._separator_widgets:
180
+ if index > 0:
181
+ # Remove the separator before this expander
182
+ sep_index = index - 1
183
+ elif len(self._expanders) > 1:
184
+ # Removing first expander - remove the separator after it
185
+ sep_index = 0
186
+ else:
187
+ sep_index = None
188
+
189
+ if sep_index is not None and sep_index < len(self._separator_widgets):
190
+ sep = self._separator_widgets.pop(sep_index)
191
+ sep.destroy()
192
+
193
+ # Remove expander from dict/list and destroy
194
+ del self._expanders[key]
195
+ self._expander_order.remove(key)
196
+ expander.destroy()
197
+
198
+ # Handle allow_collapse_all=False constraint
199
+ if not self._allow_collapse_all and was_expanded and self._expanders:
200
+ # The removed expander was open - need to open another
201
+ expander_list = [self._expanders[k] for k in self._expander_order]
202
+ any_open = any(exp['expanded'] for exp in expander_list)
203
+ if not any_open:
204
+ expander_list[0].expand()
205
+
206
+ # Fire change event
207
+ if self._expanders:
208
+ expander_list = [self._expanders[k] for k in self._expander_order]
209
+ self.event_generate('<<AccordionChange>>', data={
210
+ 'expanded': [exp for exp in expander_list if exp['expanded']]
211
+ })
212
+
213
+ def _on_expander_toggle(self, expander: Expander, event):
214
+ """Handle expander toggle events."""
215
+ if self._updating:
216
+ return
217
+
218
+ self._updating = True
219
+ try:
220
+ is_expanded = event.data.get('expanded', False)
221
+ expander_list = [self._expanders[k] for k in self._expander_order]
222
+
223
+ if is_expanded:
224
+ # Expander was just opened
225
+ if not self._allow_multiple:
226
+ # Collapse all others
227
+ for exp in expander_list:
228
+ if exp is not expander and exp['expanded']:
229
+ exp.collapse()
230
+ else:
231
+ # Expander was just closed
232
+ if not self._allow_collapse_all:
233
+ # Check if any are still open
234
+ any_open = any(exp['expanded'] for exp in expander_list)
235
+ if not any_open:
236
+ # Re-open this one - can't collapse all
237
+ expander.expand()
238
+ return
239
+
240
+ # Fire change event
241
+ self.event_generate('<<AccordionChange>>', data={
242
+ 'expanded': [exp for exp in expander_list if exp['expanded']]
243
+ })
244
+ finally:
245
+ self._updating = False
246
+
247
+ def item(self, key: str) -> Expander:
248
+ """Get an expander by its key.
249
+
250
+ Args:
251
+ key: The key of the expander to retrieve.
252
+
253
+ Returns:
254
+ The Expander instance.
255
+
256
+ Raises:
257
+ KeyError: If no expander with the given key exists.
258
+ """
259
+ if key not in self._expanders:
260
+ raise KeyError(f"No expander with key '{key}'")
261
+ return self._expanders[key]
262
+
263
+ def items(self) -> tuple[Expander, ...]:
264
+ """Get all expander widgets in order.
265
+
266
+ Returns:
267
+ A tuple of all Expander instances in the order they were added.
268
+ """
269
+ return tuple(self._expanders[key] for key in self._expander_order)
270
+
271
+ def keys(self) -> tuple[str, ...]:
272
+ """Get all expander keys in order.
273
+
274
+ Returns:
275
+ A tuple of all expander keys in the order they were added.
276
+ """
277
+ return tuple(self._expander_order)
278
+
279
+ def configure_item(self, key: str, option: str = None, **kwargs: Any):
280
+ """Configure a specific expander by its key.
281
+
282
+ Args:
283
+ key: The key of the expander to configure.
284
+ option: If provided, return the value of this option.
285
+ **kwargs: Configuration options to apply to the expander.
286
+
287
+ Returns:
288
+ If option is provided, returns the value of that option.
289
+ """
290
+ expander = self.item(key)
291
+ if option is not None:
292
+ return expander.cget(option)
293
+ expander.configure(**kwargs)
294
+
295
+ def expand(self, key: str):
296
+ """Expand the expander with the given key.
297
+
298
+ Args:
299
+ key (str): Key of the expander to expand.
300
+ """
301
+ if key in self._expanders:
302
+ self._expanders[key].expand()
303
+
304
+ def collapse(self, key: str):
305
+ """Collapse the expander with the given key.
306
+
307
+ Args:
308
+ key (str): Key of the expander to collapse.
309
+
310
+ Note:
311
+ If allow_collapse_all=False and this is the only open expander,
312
+ this call will be ignored.
313
+ """
314
+ if key in self._expanders:
315
+ exp = self._expanders[key]
316
+ if not self._allow_collapse_all:
317
+ # Check if this is the only open one
318
+ expander_list = [self._expanders[k] for k in self._expander_order]
319
+ open_count = sum(1 for e in expander_list if e['expanded'])
320
+ if open_count <= 1 and exp['expanded']:
321
+ return # Can't collapse the last one
322
+ exp.collapse()
323
+
324
+ def expand_all(self):
325
+ """Expand all expanders (only effective when allow_multiple=True)."""
326
+ if not self._allow_multiple:
327
+ return
328
+ for exp in self._expanders.values():
329
+ exp.expand()
330
+
331
+ def collapse_all(self):
332
+ """Collapse all expanders (only effective when allow_collapse_all=True)."""
333
+ if not self._allow_collapse_all:
334
+ return
335
+ for exp in self._expanders.values():
336
+ exp.collapse()
337
+
338
+ @property
339
+ def expanded(self) -> list[Expander]:
340
+ """Get the list of currently expanded Expanders."""
341
+ return [self._expanders[k] for k in self._expander_order if self._expanders[k]['expanded']]
342
+
343
+ @configure_delegate('allow_multiple')
344
+ def _delegate_allow_multiple(self, value=None):
345
+ """Get or set whether multiple sections can be open at once."""
346
+ if value is None:
347
+ return self._allow_multiple
348
+ self._allow_multiple = value
349
+ return None
350
+
351
+ @configure_delegate('allow_collapse_all')
352
+ def _delegate_allow_collapse_all(self, value=None):
353
+ """Get or set whether all sections can be collapsed."""
354
+ if value is None:
355
+ return self._allow_collapse_all
356
+ self._allow_collapse_all = value
357
+ return None
358
+
359
+ @configure_delegate('show_separators')
360
+ def _delegate_show_separators(self, value=None):
361
+ """Get or set whether separators are shown between sections."""
362
+ if value is None:
363
+ return self._show_separators
364
+ self._show_separators = value
365
+ return None
366
+
367
+ def on_accordion_changed(self, callback: Callable) -> str:
368
+ """Bind callback to `<<AccordionChange>>` events.
369
+
370
+ Args:
371
+ callback: Function to call when expanded sections change.
372
+ Receives event with `event.data = {'expanded': list[Expander]}`.
373
+
374
+ Returns:
375
+ Bind ID that can be passed to `off_accordion_changed` to remove this callback.
376
+ """
377
+ return self.bind('<<AccordionChange>>', callback, add='+')
378
+
379
+ def off_accordion_changed(self, bind_id: str = None):
380
+ """Unbind `<<AccordionChange>>` callback(s).
381
+
382
+ Args:
383
+ bind_id (str | None): Bind ID returned by `on_accordion_changed`. If None, unbinds all.
384
+ """
385
+ self.unbind('<<AccordionChange>>', bind_id)