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,478 @@
1
+ """Tabs widget - a tab bar container for TabItem widgets."""
2
+ from __future__ import annotations
3
+
4
+ __all__ = ['Tabs']
5
+
6
+ import tkinter as tk
7
+ from tkinter import Variable
8
+ from typing import Any, Callable, Literal, TYPE_CHECKING, Union
9
+
10
+ from bootstack.widgets.primitives.packframe import PackFrame
11
+ from bootstack.widgets.primitives.frame import Frame
12
+ from bootstack.widgets.primitives.separator import Separator
13
+ from bootstack.widgets.primitives.button import Button
14
+ from bootstack.widgets.composites.tabs.tabitem import TabItem
15
+ from bootstack.widgets.mixins.configure_mixin import configure_delegate
16
+ from bootstack.widgets.types import Master
17
+
18
+ if TYPE_CHECKING:
19
+ from bootstack.core.signals import Signal
20
+
21
+
22
+ class Tabs(Frame):
23
+ """A container widget for grouping TabItem widgets.
24
+
25
+ Tabs provides a tab bar with optional divider. It manages the layout,
26
+ orientation, and styling of child TabItems.
27
+
28
+ !!! note "Events"
29
+ - `<<TabSelect>>`: Fired when a tab is selected (bubbled from TabItem).
30
+ - `<<TabClose>>`: Fired when a tab's close button is clicked (bubbled from TabItem).
31
+ - `<<TabAdd>>`: Fired when the add button is clicked (if enable_adding=True).
32
+
33
+ Attributes:
34
+ orient (str): The orientation of the tab bar ('horizontal' or 'vertical').
35
+ variant (str): The visual style variant ('pill' or 'bar').
36
+ """
37
+
38
+ def __init__(
39
+ self,
40
+ master: Master = None,
41
+ orient: Literal['horizontal', 'vertical'] = 'horizontal',
42
+ variant: Literal['pill', 'bar'] = 'bar',
43
+ show_divider: bool = None,
44
+ compound: Literal['left', 'right', 'top', 'bottom', 'center', 'none'] = 'left',
45
+ tab_width: Union[None, int, Literal['stretch']] = None,
46
+ tab_padding: tuple = (12, 8),
47
+ tab_anchor: str = None,
48
+ enable_closing: Union[bool, Literal['hover']] = False,
49
+ enable_adding: bool = False,
50
+ variable: Variable = None,
51
+ signal: 'Signal[Any]' = None,
52
+ accent: str = None,
53
+ **kwargs
54
+ ):
55
+ """Create a Tabs widget.
56
+
57
+ Args:
58
+ master: Parent widget. If None, uses the default root window.
59
+ orient: Orientation of the tab bar. 'horizontal' places tabs in a row,
60
+ 'vertical' places tabs in a column. Default is 'horizontal'.
61
+ variant: Visual style variant ('pill' or 'bar').
62
+ Default is 'bar'.
63
+ show_divider: Whether to show a divider line. If None (default),
64
+ automatically set to True for 'bar' variant, False for others.
65
+ compound: How to position icon relative to text in tabs.
66
+ Passed to all TabItems. Default is 'left'.
67
+ tab_width: Width of tabs. None for auto-sizing, an integer for
68
+ fixed character width, or 'stretch' to expand tabs to fill
69
+ available space (horizontal only). Default is None.
70
+ tab_padding: Padding for all tabs as (horizontal, vertical).
71
+ Default is (12, 8).
72
+ tab_anchor: Anchor for tab text/icon alignment. If None, defaults
73
+ to 'w' for vertical orientation, 'center' for horizontal.
74
+ enable_closing: Default close button visibility for all tabs.
75
+ True=always visible, False=hidden, 'hover'=visible on hover.
76
+ Can be overridden per-tab via `closable` in add_tab().
77
+ enable_adding: If True, shows an "add" button. In horizontal
78
+ orientation, shows a plus icon on the right. In vertical
79
+ orientation, shows "New Tab" at the bottom. Fires `<<TabAdd>>`
80
+ event when clicked.
81
+ variable: Tk variable for tracking selected tab value.
82
+ signal: Reactive Signal for tracking selected tab value.
83
+ accent: Accent token for styling tabs.
84
+ **kwargs: Additional arguments passed to Frame.
85
+ """
86
+ super().__init__(master=master, **kwargs)
87
+
88
+ self._orient = orient
89
+ self._variant = variant
90
+ self._compound = compound
91
+ self._tab_width = tab_width
92
+ self._tab_padding = tab_padding
93
+ self._enable_closing = enable_closing
94
+ self._enable_adding = enable_adding
95
+ self._accent = accent
96
+
97
+ # Handle variable/signal setup
98
+ if signal is not None:
99
+ # Signal provided - extract its variable
100
+ self._signal = signal
101
+ self._variable = signal.var
102
+ elif variable is not None:
103
+ # Variable provided - wrap in Signal
104
+ from bootstack.core.signals import Signal
105
+ self._variable = variable
106
+ self._signal = Signal.from_variable(variable)
107
+ else:
108
+ # Neither provided - create internal variable and signal
109
+ from bootstack.core.signals import Signal
110
+ self._variable = tk.StringVar()
111
+ self._signal = Signal.from_variable(self._variable)
112
+
113
+ # Default anchor based on orientation
114
+ if tab_anchor is None:
115
+ self._tab_anchor = 'w' if orient == 'vertical' else 'center'
116
+ else:
117
+ self._tab_anchor = tab_anchor
118
+
119
+ # Determine show_divider default based on variant
120
+ if show_divider is None:
121
+ self._show_divider = variant == 'bar'
122
+ else:
123
+ self._show_divider = show_divider
124
+
125
+ # Set direction based on orient
126
+ direction = 'horizontal' if orient == 'horizontal' else 'vertical'
127
+
128
+ # Gap between tabs
129
+ gap = 0
130
+
131
+ # Internal divider widget
132
+ self._divider: Separator | None = None
133
+
134
+ # Internal add button
135
+ self._add_button: Button | None = None
136
+
137
+ # Create internal PackFrame for tabs
138
+ self._tab_bar = PackFrame(
139
+ self,
140
+ direction=direction,
141
+ gap=gap,
142
+ )
143
+
144
+ # Layout tab bar and divider
145
+ if orient == 'horizontal':
146
+ self._tab_bar.pack(side='top', fill='x')
147
+ if self._show_divider:
148
+ self._divider = Separator(self, orient='horizontal')
149
+ self._divider.pack(side='top', fill='x')
150
+ else:
151
+ self._tab_bar.pack(side='left', fill='y')
152
+ if self._show_divider:
153
+ self._divider = Separator(self, orient='vertical')
154
+ self._divider.pack(side='left', fill='y')
155
+
156
+ # Create add button if enabled (must be after tab_bar is created)
157
+ if enable_adding:
158
+ self._create_add_button()
159
+
160
+ # Tab tracking by key
161
+ self._tabs: dict[str, TabItem] = {}
162
+ self._tab_order: list[str] = []
163
+ self._counter = 0 # For auto-generating keys
164
+
165
+ def _create_divider(self):
166
+ """Create the divider separator widget."""
167
+ if self._divider is not None:
168
+ return
169
+ if self._orient == 'horizontal':
170
+ self._divider = Separator(self, orient='horizontal')
171
+ self._divider.pack(side='top', fill='x')
172
+ else:
173
+ self._divider = Separator(self, orient='vertical')
174
+ self._divider.pack(side='left', fill='y')
175
+
176
+ def _destroy_divider(self):
177
+ """Remove the divider widget."""
178
+ if self._divider is not None:
179
+ self._divider.pack_forget()
180
+ self._divider.destroy()
181
+ self._divider = None
182
+
183
+ def _create_add_button(self):
184
+ """Create the add button widget."""
185
+ if self._add_button is not None:
186
+ return
187
+
188
+ if self._orient == 'horizontal':
189
+ # Plus icon only
190
+ self._add_button = Button(
191
+ self._tab_bar,
192
+ icon='plus',
193
+ icon_only=True,
194
+ variant='ghost',
195
+ command=self._on_add_click,
196
+ )
197
+ self._add_button.pack()
198
+ else:
199
+ # "New Tab" with plus icon
200
+ self._add_button = Button(
201
+ self._tab_bar,
202
+ text='New',
203
+ icon='plus',
204
+ variant='ghost',
205
+ padding=2,
206
+ command=self._on_add_click,
207
+ anchor='w',
208
+ )
209
+ self._add_button.pack(fill='x')
210
+
211
+ def _destroy_add_button(self):
212
+ """Remove the add button widget."""
213
+ if self._add_button is not None:
214
+ self._add_button.pack_forget()
215
+ self._add_button.destroy()
216
+ self._add_button = None
217
+
218
+ def _on_add_click(self):
219
+ """Handle add button click."""
220
+ self.event_generate('<<TabAdd>>')
221
+
222
+ def on_tab_added(self, callback: Callable) -> str:
223
+ """Bind to `<<TabAdd>>` event.
224
+
225
+ Args:
226
+ callback: Function to call when add button is clicked.
227
+
228
+ Returns:
229
+ Binding identifier for use with off_tab_added().
230
+ """
231
+ return self.bind('<<TabAdd>>', callback, add='+')
232
+
233
+ def off_tab_added(self, bind_id: str | None = None) -> None:
234
+ """Unbind from <<TabAdd>> event."""
235
+ self.unbind('<<TabAdd>>', bind_id)
236
+
237
+ def add(
238
+ self,
239
+ text: str = "",
240
+ *,
241
+ key: str = None,
242
+ icon: str | dict = None,
243
+ value: Any = None,
244
+ closable: Union[bool, Literal['hover']] = None,
245
+ close_command: Callable = None,
246
+ command: Callable = None,
247
+ **kwargs
248
+ ) -> TabItem:
249
+ """Add a new tab to the tab bar.
250
+
251
+ Args:
252
+ text: Text to display on the tab.
253
+ key: Unique identifier for the tab. Auto-generated if not provided.
254
+ icon: Icon to display on the tab.
255
+ value: Value associated with this tab for selection tracking.
256
+ If None, defaults to the key.
257
+ closable: Close button visibility (True, False, or 'hover').
258
+ If None, uses the widget's `enable_closing` setting.
259
+ close_command: Callback when close button is clicked.
260
+ command: Callback when tab is selected.
261
+ **kwargs: Additional arguments passed to TabItem.
262
+
263
+ Returns:
264
+ The created TabItem widget.
265
+
266
+ Raises:
267
+ ValueError: If a tab with the same key already exists.
268
+ """
269
+ # Auto-generate key if not provided
270
+ if key is None:
271
+ key = f"tab_{self._counter}"
272
+ self._counter += 1
273
+
274
+ if key in self._tabs:
275
+ raise ValueError(f"A tab with the key '{key}' already exists.")
276
+
277
+ # Default value to key if not specified
278
+ if value is None:
279
+ value = key
280
+
281
+ # Use widget-level default if not specified
282
+ if closable is None:
283
+ closable = self._enable_closing
284
+
285
+ # Apply container defaults
286
+ tab_kwargs = {
287
+ 'compound': self._compound,
288
+ 'variant': self._variant,
289
+ 'orient': self._orient,
290
+ 'padding': self._tab_padding,
291
+ 'anchor': self._tab_anchor,
292
+ }
293
+
294
+ # Apply tab_width if specified (not 'stretch')
295
+ if self._tab_width is not None and self._tab_width != 'stretch':
296
+ tab_kwargs['width'] = self._tab_width
297
+
298
+ # Apply accent if specified
299
+ if self._accent is not None:
300
+ tab_kwargs['accent'] = self._accent
301
+
302
+ # Pass signal to TabItem for selection sync
303
+ tab_kwargs['signal'] = self._signal
304
+
305
+ # User kwargs override defaults
306
+ tab_kwargs.update(kwargs)
307
+
308
+ tab = TabItem(
309
+ self._tab_bar,
310
+ text=text,
311
+ icon=icon,
312
+ value=value,
313
+ closable=closable,
314
+ close_command=close_command,
315
+ command=command,
316
+ **tab_kwargs
317
+ )
318
+
319
+ # Determine pack options
320
+ pack_opts = {'fill': 'x'}
321
+ if self._tab_width == 'stretch' and self._orient == 'horizontal':
322
+ pack_opts['expand'] = True
323
+
324
+ # Insert before add button if it exists, otherwise append
325
+ if self._add_button is not None:
326
+ tab.pack(before=self._add_button, **pack_opts)
327
+ else:
328
+ tab.pack(**pack_opts)
329
+
330
+ # Track tab by key
331
+ self._tabs[key] = tab
332
+ self._tab_order.append(key)
333
+
334
+ # Auto-select first tab
335
+ if len(self._tabs) == 1:
336
+ self._variable.set(value)
337
+
338
+ return tab
339
+
340
+ def remove(self, key: str) -> None:
341
+ """Remove a tab by its key.
342
+
343
+ Args:
344
+ key: The key of the tab to remove.
345
+
346
+ Raises:
347
+ KeyError: If no tab with the given key exists.
348
+ """
349
+ if key not in self._tabs:
350
+ raise KeyError(f"No tab with key '{key}'")
351
+
352
+ tab = self._tabs.pop(key)
353
+ self._tab_order.remove(key)
354
+ tab.pack_forget()
355
+ tab.destroy()
356
+
357
+ def item(self, key: str) -> TabItem:
358
+ """Get a tab by its key.
359
+
360
+ Args:
361
+ key: The key of the tab to retrieve.
362
+
363
+ Returns:
364
+ The TabItem instance.
365
+
366
+ Raises:
367
+ KeyError: If no tab with the given key exists.
368
+ """
369
+ if key not in self._tabs:
370
+ raise KeyError(f"No tab with key '{key}'")
371
+ return self._tabs[key]
372
+
373
+ def items(self) -> tuple[TabItem, ...]:
374
+ """Get all tab widgets in order.
375
+
376
+ Returns:
377
+ A tuple of all TabItem instances in the order they were added.
378
+ """
379
+ return tuple(self._tabs[key] for key in self._tab_order)
380
+
381
+ def keys(self) -> tuple[str, ...]:
382
+ """Get all tab keys in order.
383
+
384
+ Returns:
385
+ A tuple of all tab keys in the order they were added.
386
+ """
387
+ return tuple(self._tab_order)
388
+
389
+ def configure_item(self, key: str, option: str = None, **kwargs: Any):
390
+ """Configure a specific tab by its key.
391
+
392
+ Args:
393
+ key: The key of the tab to configure.
394
+ option: If provided, return the value of this option.
395
+ **kwargs: Configuration options to apply to the tab.
396
+
397
+ Returns:
398
+ If option is provided, returns the value of that option.
399
+ """
400
+ tab = self.item(key)
401
+ if option is not None:
402
+ return tab.cget(option)
403
+ tab.configure(**kwargs)
404
+
405
+ @configure_delegate('orient')
406
+ def _delegate_orient(self, value=None):
407
+ """Get orientation (read-only after creation)."""
408
+ if value is None:
409
+ return self._orient
410
+ raise ValueError("orient cannot be changed after creation")
411
+
412
+ @configure_delegate('variant')
413
+ def _delegate_variant(self, value=None):
414
+ """Get variant (read-only after creation)."""
415
+ if value is None:
416
+ return self._variant
417
+ raise ValueError("variant cannot be changed after creation")
418
+
419
+ @property
420
+ def variable(self) -> tk.Variable:
421
+ """Get the underlying tk.Variable for tab selection."""
422
+ return self._variable
423
+
424
+ @property
425
+ def signal(self) -> 'Signal[Any]':
426
+ """Get the Signal for tab selection."""
427
+ return self._signal
428
+
429
+ @configure_delegate('show_divider')
430
+ def _delegate_show_divider(self, value=None):
431
+ """Get or set whether the divider is shown."""
432
+ if value is None:
433
+ return self._show_divider
434
+ if value != self._show_divider:
435
+ self._show_divider = value
436
+ if value:
437
+ self._create_divider()
438
+ else:
439
+ self._destroy_divider()
440
+
441
+ def get(self) -> str:
442
+ """Return the currently selected tab value."""
443
+ return self._variable.get()
444
+
445
+ def set(self, value: str) -> None:
446
+ """Set the selected tab value."""
447
+ self._variable.set(value)
448
+
449
+ @property
450
+ def value(self) -> str:
451
+ """Get or set the selected tab value."""
452
+ return self.get()
453
+
454
+ @value.setter
455
+ def value(self, value: str) -> None:
456
+ self.set(value)
457
+
458
+ @configure_delegate('value')
459
+ def _delegate_value(self, value=None):
460
+ """Get or set the value via configure."""
461
+ if value is None:
462
+ return self.get()
463
+ self.set(value)
464
+
465
+ def on_tab_changed(self, callback: Callable) -> Any:
466
+ """Subscribe to tab selection changes.
467
+
468
+ Args:
469
+ callback: Function called with the new selected value.
470
+
471
+ Returns:
472
+ Subscription ID for use with off_tab_changed().
473
+ """
474
+ return self._signal.subscribe(callback)
475
+
476
+ def off_tab_changed(self, bind_id: Any) -> None:
477
+ """Unsubscribe from tab selection changes."""
478
+ self._signal.unsubscribe(bind_id)