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,248 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import StringVar
4
+ from typing import Any, Callable, Literal, Optional, TYPE_CHECKING, TypedDict
5
+
6
+ from typing_extensions import Unpack
7
+
8
+ from bootstack.widgets.composites.contextmenu import ContextMenu, ContextMenuItem
9
+ from bootstack.widgets.primitives.menubutton import MenuButton
10
+ from bootstack.widgets.mixins import configure_delegate
11
+ from bootstack.widgets.types import Master
12
+
13
+ if TYPE_CHECKING:
14
+ from bootstack.core.signals import Signal
15
+
16
+
17
+ class OptionMenuKwargs(TypedDict, total=False):
18
+ command: Optional[Callable[[], Any]]
19
+ image: Any
20
+ icon: Any
21
+ icon_only: bool
22
+ compound: Literal['text', 'image', 'top', 'bottom', 'left', 'right', 'center', 'none'] | str
23
+ padding: Any
24
+ width: int
25
+ underline: int
26
+ state: Literal['normal', 'active', 'disabled', 'readonly'] | str
27
+ takefocus: Any
28
+ style: str
29
+ class_: str
30
+ cursor: str
31
+ default: Any
32
+ name: str
33
+ textvariable: Any
34
+ textsignal: Signal[str]
35
+ bootstyle: str # DEPRECATED: Use accent and variant instead
36
+ accent: str
37
+ variant: str
38
+ surface: str
39
+ style_options: dict[str, Any]
40
+ show_dropdown_button: bool
41
+ dropdown_button_icon: str | dict
42
+
43
+
44
+ class OptionMenu(MenuButton):
45
+ """A single-selection dropdown menu backed by a ContextMenu.
46
+
47
+ Renders as a `MenuButton` with a chevron icon. Clicking the button opens
48
+ a popup menu containing the provided options as radiobutton items. Selecting
49
+ an item updates the displayed text and fires a `<<Change>>` event.
50
+
51
+ !!! note "Events"
52
+ - `<<Change>>`: Fired when the selected value changes.
53
+ `event.data = {'value': Any}`
54
+ """
55
+
56
+ def __init__(
57
+ self,
58
+ master: Master = None,
59
+ value: Any = None,
60
+ options: list[Any] = None,
61
+ **kwargs: Unpack[OptionMenuKwargs],
62
+ ):
63
+ """Create an OptionMenu backed by a ContextMenu.
64
+
65
+ !!! note "Events"
66
+ - `<<Change>>`: Fired when the selected value changes. `event.data = {'value': Any}`
67
+
68
+ Args:
69
+ master: Parent widget. If None, uses the default root window.
70
+ value: Initial selected value.
71
+ options (list): List of values to populate the menu.
72
+
73
+ Other Parameters:
74
+ command (Callable): Callback invoked when the value changes via menu selection.
75
+ image (PhotoImage): Tk image to display.
76
+ icon (str | dict): Bootstyle icon spec for the label content.
77
+ icon_only (bool): Whether to reserve label padding when showing only an icon.
78
+ compound (str): Placement of image relative to text.
79
+ padding (int | tuple): Extra padding around the menubutton content.
80
+ width (int): Width of the menubutton.
81
+ underline (int): Index of underlined character in text.
82
+ state (str): Widget state ('normal', 'active', 'disabled', 'readonly').
83
+ takefocus (bool): Participation in focus traversal.
84
+ style (str): Explicit ttk style name (overrides accent/variant).
85
+ textvariable (Variable): Existing Tk variable to bind; new StringVar created if omitted.
86
+ textsignal (Signal[str]): Signal bound to the textvariable.
87
+ accent (str): Accent token for styling, e.g. 'primary', 'danger', 'success'.
88
+ variant (str): Style variant, e.g. 'solid', 'outline'.
89
+ bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
90
+ Combined style tokens (e.g., 'primary-outline').
91
+ surface (str): Surface token for style.
92
+ style_options (dict): Dict forwarded to the style builder (e.g., icon_only, surface).
93
+ show_dropdown_button (bool): Toggle visibility of the dropdown chevron.
94
+ dropdown_button_icon (str | dict): Icon name for the chevron; defaults to 'caret-down-fill'.
95
+ """
96
+ style_options = kwargs.pop('style_options', {})
97
+ style_options.update(
98
+ self._capture_style_options(
99
+ options=['icon_only', 'icon', 'show_dropdown_button', 'dropdown_button_icon'],
100
+ source=kwargs
101
+ )
102
+ )
103
+
104
+ self._bind_id = None
105
+ self._menu_options = options if options is not None else []
106
+
107
+ # Store the textvariable if provided, or create a new one
108
+ self._textvariable = kwargs.pop('textvariable', None)
109
+ if self._textvariable is None:
110
+ self._textvariable = StringVar(value=str(value) if value is not None else "")
111
+
112
+ super().__init__(master, text=value, **kwargs)
113
+
114
+ # Configure the menubutton to use the textvariable
115
+ self.configure(textvariable=self._textvariable)
116
+
117
+ # Bind signal to change event
118
+ self._bind_id = self._bind_change_event()
119
+
120
+ # Create menu items that update the shared variable
121
+ self._context_menu = self._build_context_menu()
122
+
123
+ # Bind menu display to button events
124
+ self.bind('<Button-1>', lambda _: self.show_menu(), add="+")
125
+ self.bind('<Return>', lambda _: self.show_menu(), add="+")
126
+ self.bind('<KP_Enter>', lambda _: self.show_menu(), add="+")
127
+
128
+ def _bind_change_event(self):
129
+ """(Re)bind textsignal to emit <<Change>> Tk events."""
130
+ if self._bind_id is not None:
131
+ self.textsignal.unsubscribe(self._bind_id)
132
+ return self.textsignal.subscribe(lambda v: self.event_generate('<<Change>>', data={"value": v}))
133
+
134
+ def _build_context_menu(self):
135
+ # Affordance baked into the button image (focus ring + border line in
136
+ # source-px); aligning the menu's left edge to it matches the visible
137
+ # button border the same way the combobox popdown does.
138
+ from bootstack.style.bootstyle_builder_base import BootstyleBuilderBase
139
+ offset_x = BootstyleBuilderBase.scale_from_source(10)
140
+
141
+ density = self.configure_style_options('density') or 'default'
142
+
143
+ menu_items = [
144
+ ContextMenuItem(
145
+ type="radiobutton",
146
+ text=str(item),
147
+ variable=self._textvariable,
148
+ value=str(item)
149
+ )
150
+ for item in self._menu_options
151
+ ]
152
+ return ContextMenu(
153
+ self, target=self, items=menu_items,
154
+ anchor="nw", attach="sw",
155
+ offset=(offset_x, 0),
156
+ density=density,
157
+ # OptionMenu drives activation via `show_menu` (left-click,
158
+ # Return/KP_Enter), not ContextMenu's auto-trigger.
159
+ trigger=None,
160
+ )
161
+
162
+ def show_menu(self):
163
+ """Show the dropdown menu unless disabled or readonly."""
164
+ if not self.instate(("!disabled", "!readonly")):
165
+ return
166
+ # Match the menu's minimum width to the visible button width so the
167
+ # dropdown never renders narrower than its trigger.
168
+ from bootstack.style.bootstyle_builder_base import BootstyleBuilderBase
169
+ affordance = BootstyleBuilderBase.scale_from_source(10)
170
+ target_w = self.winfo_width() - 2 * affordance
171
+ if target_w > 0:
172
+ self._context_menu.configure(minwidth=max(150, target_w))
173
+ self._context_menu.show()
174
+
175
+ def get(self) -> str:
176
+ """Return the current value."""
177
+ return self._textvariable.get()
178
+
179
+ def set(self, value: Any) -> None:
180
+ """Set the current value (coerced to string)."""
181
+ self._textvariable.set(str(value))
182
+
183
+ @property
184
+ def value(self) -> str:
185
+ """Get or set the current value."""
186
+ return self.get()
187
+
188
+ @value.setter
189
+ def value(self, value: Any) -> None:
190
+ self.set(value)
191
+
192
+ def on_changed(self, callback: Callable) -> str:
193
+ """Bind to `<<Change>>`. Callback receives `event.data = {'value': Any}`."""
194
+ return self.bind('<<Change>>', callback, add="+")
195
+
196
+ def off_changed(self, bind_id: str | None = None) -> None:
197
+ """Unbind from `<<Change>>`."""
198
+ self.unbind('<<Change>>', bind_id)
199
+
200
+ @configure_delegate('options')
201
+ def _delegate_options(self, value=None):
202
+ """Get or set the menu options list."""
203
+ if value is None:
204
+ return self._menu_options
205
+ else:
206
+ self._menu_options = value
207
+ if self._context_menu:
208
+ self._context_menu.destroy()
209
+ self._context_menu = self._build_context_menu()
210
+ return None
211
+
212
+ @configure_delegate('value')
213
+ def _delegate_value(self, value):
214
+ """Get or set the current value."""
215
+ if value is None:
216
+ return self.value
217
+ else:
218
+ self.value = value
219
+ return None
220
+
221
+ @configure_delegate('textsignal')
222
+ def _delegate_textsignal(self, value=None):
223
+ """Get or set the textsignal binding."""
224
+ if value is None:
225
+ return super()._delegate_textsignal()
226
+ else:
227
+ super()._delegate_textsignal(value)
228
+ self._bind_change_event()
229
+ return None
230
+
231
+ @configure_delegate('show_dropdown_button')
232
+ def _delegate_show_dropdown_button(self, value=None):
233
+ """Get or set visibility of the dropdown chevron."""
234
+ if value is None:
235
+ return self.configure_style_options('show_dropdown_button')
236
+ else:
237
+ self.configure_style_options(show_dropdown_button=value)
238
+ return self.rebuild_style()
239
+
240
+ @configure_delegate('dropdown_button_icon')
241
+ def _delegate_dropdown_button_icon(self, value):
242
+ """Get or set the dropdown chevron icon name."""
243
+ if value is None:
244
+ return self.configure_style_options('dropdown_button_icon')
245
+ else:
246
+ self.configure_style_options(dropdown_button_icon=value)
247
+ return self.rebuild_style()
248
+
@@ -0,0 +1,228 @@
1
+ from __future__ import annotations
2
+
3
+ import tkinter as tk
4
+ from typing import Literal, Optional, Any
5
+
6
+ from bootstack.widgets.primitives.frame import Frame
7
+ from bootstack.widgets.mixins.configure_mixin import configure_delegate
8
+ from bootstack.widgets.types import Master
9
+
10
+ Direction = Literal["vertical", "horizontal", "row", "column", "row-reverse", "column-reverse"]
11
+ Fill = Literal["none", "x", "y", "both"]
12
+ Side = Literal["top", "bottom", "left", "right"]
13
+ Anchor = Literal["n", "ne", "e", "se", "s", "sw", "w", "nw", "center"]
14
+
15
+
16
+ class PackFrame(Frame):
17
+ """A Frame with simplified pack-based layout management.
18
+
19
+ PackFrame extends the bootstack Frame with automatic pack-based
20
+ layout management, including support for direction, gap spacing,
21
+ and default fill/expand behavior.
22
+
23
+ Children packed into this frame automatically receive the frame's
24
+ default layout options. Simply use the standard `pack()` method
25
+ on child widgets — no special `add()` method is needed.
26
+
27
+ Example:
28
+ ```python
29
+ frame = PackFrame(direction="vertical", gap=10, fill_items="x")
30
+ Label(frame, text="First").pack()
31
+ Label(frame, text="Second").pack()
32
+ Button(frame, text="Click").pack(expand=True) # override default
33
+ ```
34
+ """
35
+
36
+ SIDE_MAP: dict[Direction, Side] = {
37
+ "vertical": "top",
38
+ "column": "top",
39
+ "column-reverse": "bottom",
40
+ "horizontal": "left",
41
+ "row": "left",
42
+ "row-reverse": "right",
43
+ }
44
+
45
+ def __init__(
46
+ self,
47
+ master: Master = None,
48
+ *,
49
+ direction: Direction = "vertical",
50
+ gap: int = 0,
51
+ fill_items: Optional[Fill] = None,
52
+ expand_items: Optional[bool] = None,
53
+ anchor_items: Optional[Anchor] = None,
54
+ propagate: Optional[bool] = None,
55
+ **kwargs: Any,
56
+ ) -> None:
57
+ """Create a PackFrame with automatic pack-based layout.
58
+
59
+ Args:
60
+ master: Parent widget. If None, uses the default root window.
61
+ direction: Layout direction — `'vertical'`, `'horizontal'`,
62
+ `'row'`, `'column'`, `'row-reverse'`, or `'column-reverse'`.
63
+ Defaults to `'vertical'`.
64
+ gap: Spacing between children in pixels. Defaults to 0.
65
+ fill_items: Default `fill` option for children
66
+ (`'none'`, `'x'`, `'y'`, or `'both'`). If None, no default fill
67
+ is applied.
68
+ expand_items: Default `expand` option for children. If None, no
69
+ default expand is applied.
70
+ anchor_items: Default `anchor` for children. If None, no default
71
+ anchor is applied.
72
+ propagate: If False, the frame will not resize to fit its contents.
73
+ Defaults to None (Tk default behaviour).
74
+ **kwargs: Additional keyword arguments forwarded to `Frame`.
75
+ """
76
+ super().__init__(master, **kwargs)
77
+
78
+ self._direction = direction
79
+ self._gap = gap
80
+ self._default_fill = fill_items
81
+ self._default_expand = expand_items
82
+ self._default_anchor = anchor_items
83
+
84
+ # Ordered list of (widget, user_options) tuples for gap tracking
85
+ self._managed: list[tuple[tk.Widget, dict[str, Any]]] = []
86
+
87
+ if propagate is not None:
88
+ self.pack_propagate(propagate)
89
+
90
+ @property
91
+ def _side(self) -> Side:
92
+ """Get the pack side based on direction."""
93
+ return self.SIDE_MAP.get(self._direction, "top")
94
+
95
+ @configure_delegate('direction')
96
+ def _delegate_direction(self, value=None) -> Direction:
97
+ """Get or set the layout direction."""
98
+ if value is None:
99
+ return self._direction
100
+ self._direction = value
101
+ # Repack all widgets with new direction
102
+ self._repack_all()
103
+
104
+ @configure_delegate('gap')
105
+ def _delegate_gap(self, value=None) -> int:
106
+ """Get or set the gap between children."""
107
+ if value is None:
108
+ return self._gap
109
+ self._gap = value
110
+ # Repack all widgets with new gap
111
+ self._repack_all()
112
+
113
+ def _compute_gap(self, index: int) -> dict[str, Any]:
114
+ """Compute padding for gap based on position and direction."""
115
+ if index == 0 or self._gap == 0:
116
+ return {}
117
+
118
+ if self._direction in ("vertical", "column"):
119
+ return {"pady": (self._gap, 0)}
120
+ elif self._direction == "column-reverse":
121
+ return {"pady": (0, self._gap)}
122
+ elif self._direction in ("horizontal", "row"):
123
+ return {"padx": (self._gap, 0)}
124
+ elif self._direction == "row-reverse":
125
+ return {"padx": (0, self._gap)}
126
+ return {}
127
+
128
+ def _build_options(self, index: int, user_options: dict[str, Any]) -> dict[str, Any]:
129
+ """Build final pack options by merging defaults with user options."""
130
+ options: dict[str, Any] = {"in_": self, "side": self._side}
131
+
132
+ # Apply gap based on position
133
+ options.update(self._compute_gap(index))
134
+
135
+ # Apply container-level defaults
136
+ if self._default_fill is not None:
137
+ options["fill"] = self._default_fill
138
+ if self._default_expand is not None:
139
+ options["expand"] = self._default_expand
140
+ if self._default_anchor is not None:
141
+ options["anchor"] = self._default_anchor
142
+
143
+ # User options override everything
144
+ options.update(user_options)
145
+ return options
146
+
147
+ def _repack_all(self) -> None:
148
+ """Unpack and repack all widgets to maintain correct order and gaps."""
149
+ # Unpack all
150
+ for widget, _ in self._managed:
151
+ tk.Pack.forget(widget)
152
+
153
+ # Repack in order
154
+ for i, (widget, user_options) in enumerate(self._managed):
155
+ options = self._build_options(i, user_options)
156
+ tk.Pack.configure(widget, **options)
157
+
158
+ def _find_widget_index(self, widget: tk.Widget) -> int:
159
+ """Find index of widget in managed list, return -1 if not found."""
160
+ for i, (w, _) in enumerate(self._managed):
161
+ if w is widget:
162
+ return i
163
+ return -1
164
+
165
+ def _find_insert_index(self, before: tk.Widget = None, after: tk.Widget = None) -> int:
166
+ """Determine insertion index based on before/after options."""
167
+ if before is not None:
168
+ idx = self._find_widget_index(before)
169
+ if idx >= 0:
170
+ return idx
171
+ if after is not None:
172
+ idx = self._find_widget_index(after)
173
+ if idx >= 0:
174
+ return idx + 1
175
+ return len(self._managed)
176
+
177
+ # -------------------------------------------------------------------------
178
+ # Hook methods called by PackMixin
179
+ # -------------------------------------------------------------------------
180
+
181
+ def _on_child_pack(self, widget: tk.Widget, **options: Any) -> None:
182
+ """Hook called when a child widget calls pack().
183
+
184
+ Applies frame defaults, handles gap spacing, and tracks the widget.
185
+ """
186
+ # Check if widget is already managed (reconfigure case)
187
+ existing_idx = self._find_widget_index(widget)
188
+
189
+ # Determine insertion position from before/after
190
+ before = options.pop("before", None)
191
+ after = options.pop("after", None)
192
+
193
+ if existing_idx >= 0:
194
+ # Widget already managed - update its options
195
+ self._managed[existing_idx] = (widget, options)
196
+ self._repack_all()
197
+ else:
198
+ # New widget - find insertion point
199
+ insert_idx = self._find_insert_index(before, after)
200
+
201
+ if insert_idx < len(self._managed):
202
+ # Inserting in the middle - need to repack all
203
+ self._managed.insert(insert_idx, (widget, options))
204
+ self._repack_all()
205
+ else:
206
+ # Appending at the end - just pack it
207
+ pack_options = self._build_options(len(self._managed), options)
208
+ tk.Pack.configure(widget, **pack_options)
209
+ self._managed.append((widget, options))
210
+
211
+ def _on_child_pack_forget(self, widget: tk.Widget) -> None:
212
+ """Hook called when a child widget calls pack_forget().
213
+
214
+ Removes widget from tracking and repacks remaining widgets if needed.
215
+ """
216
+ idx = self._find_widget_index(widget)
217
+ if idx < 0:
218
+ # Not managed by us, just forget it normally
219
+ tk.Pack.forget(widget)
220
+ return
221
+
222
+ # Remove from our tracking
223
+ tk.Pack.forget(widget)
224
+ self._managed.pop(idx)
225
+
226
+ # Only repack if we removed something that affects gaps (not the last item)
227
+ if idx < len(self._managed):
228
+ self._repack_all()
@@ -0,0 +1,58 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import ttk
4
+ from typing import Any, TypedDict
5
+ from typing_extensions import Unpack
6
+
7
+ from bootstack.core.mixins.ttk_state import TtkStateMixin
8
+ from bootstack.core.mixins.widget import WidgetCapabilitiesMixin
9
+ from bootstack.widgets.internal.wrapper_base import TTKWrapperBase
10
+ from bootstack.widgets.types import Master
11
+
12
+
13
+ class PanedWindowKwargs(TypedDict, total=False):
14
+ # Standard ttk.Panedwindow options
15
+ orient: Any
16
+ padding: Any
17
+ width: int
18
+ height: int
19
+ style: str
20
+ class_: str
21
+ cursor: str
22
+ name: str
23
+
24
+ # bootstack-specific extensions
25
+ bootstyle: str # DEPRECATED: Use accent and variant instead
26
+ accent: str
27
+ variant: str
28
+ surface: str
29
+ style_options: dict[str, Any]
30
+
31
+
32
+ class PanedWindow(TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.PanedWindow):
33
+ """bootstack wrapper for `ttk.Panedwindow` with bootstyle support."""
34
+
35
+ _ttk_base = ttk.Panedwindow
36
+
37
+ def __init__(self, master: Master = None, **kwargs: Unpack[PanedWindowKwargs]) -> None:
38
+ """Create a themed bootstack Panedwindow.
39
+
40
+ Args:
41
+ master: Parent widget. If None, uses the default root window.
42
+
43
+ Other Parameters:
44
+ orient (str): Orientation of panes ('horizontal' or 'vertical').
45
+ padding (int | tuple): Extra internal padding.
46
+ width (int): Requested width in pixels.
47
+ height (int): Requested height in pixels.
48
+ style (str): Explicit ttk style name (overrides accent/variant).
49
+ accent (str): Accent token for styling, e.g. 'primary', 'secondary'.
50
+ variant (str): Style variant (if applicable).
51
+ bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
52
+ Combined style tokens.
53
+ surface (str): Optional surface token; otherwise inherited.
54
+ style_options (dict): Optional dict forwarded to the style builder.
55
+ """
56
+ super().__init__(master, **kwargs)
57
+
58
+
@@ -0,0 +1,95 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import ttk
4
+ from typing import Any, Literal, TypedDict, TYPE_CHECKING
5
+ from typing_extensions import Unpack
6
+
7
+ from bootstack.core.mixins.ttk_state import TtkStateMixin
8
+ from bootstack.core.mixins.widget import WidgetCapabilitiesMixin
9
+ from bootstack.widgets.internal.wrapper_base import TTKWrapperBase
10
+ from bootstack.widgets.mixins.configure_mixin import configure_delegate
11
+ from bootstack.widgets.types import Master
12
+ from ..mixins import SignalMixin
13
+
14
+ if TYPE_CHECKING:
15
+ from bootstack.core.signals import Signal
16
+
17
+
18
+ class ProgressbarKwargs(TypedDict, total=False):
19
+ # Standard ttk.Progressbar options
20
+ mode: Literal['determinate', 'indeterminate'] | str
21
+ orient: Any
22
+ length: Any
23
+ maximum: float
24
+ value: float
25
+ variable: Any
26
+ signal: Signal[Any]
27
+ phase: int
28
+ style: str
29
+ class_: str
30
+ cursor: str
31
+ name: str
32
+
33
+ # bootstack-specific extensions
34
+ bootstyle: str # DEPRECATED: Use accent and variant instead
35
+ accent: str
36
+ variant: str
37
+ surface: str
38
+ style_options: dict[str, Any]
39
+
40
+
41
+ class Progressbar(SignalMixin, TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Progressbar):
42
+ """bootstack wrapper for `ttk.Progressbar` with bootstyle support."""
43
+
44
+ _ttk_base = ttk.Progressbar
45
+
46
+ def __init__(self, master: Master = None, **kwargs: Unpack[ProgressbarKwargs]) -> None:
47
+ """Create a themed bootstack Progressbar.
48
+
49
+ Args:
50
+ master: Parent widget. If None, uses the default root window.
51
+
52
+ Other Parameters:
53
+ mode (str): Progress mode ('determinate' or 'indeterminate').
54
+ orient (str): Orientation of the bar ('horizontal' or 'vertical').
55
+ length (int): Requested length of the progress bar in pixels.
56
+ maximum (float): Maximum value.
57
+ value (float): Current value.
58
+ variable (Variable): Tk variable linked to the value.
59
+ signal (Signal): Reactive Signal linked to the value (auto-synced with variable).
60
+ phase (int): Animation phase for indeterminate mode.
61
+ style (str): Explicit ttk style name (overrides accent/variant).
62
+ accent (str): Accent token for styling, e.g. 'primary', 'success', 'danger'.
63
+ variant (str): Style variant, e.g. 'default', 'striped', 'thin'.
64
+ bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
65
+ Combined style tokens (e.g., 'success', 'striped').
66
+ surface (str): Optional surface token; otherwise inherited.
67
+ style_options (dict): Optional dict forwarded to the style builder.
68
+ """
69
+ super().__init__(master, **kwargs)
70
+
71
+ def get(self) -> float:
72
+ """Return the current progress value."""
73
+ return self.cget('value')
74
+
75
+ def set(self, value: float) -> None:
76
+ """Set the progress value."""
77
+ self.configure(value=value)
78
+
79
+ @property
80
+ def value(self) -> float:
81
+ """Get or set the progress value."""
82
+ return self.get()
83
+
84
+ @value.setter
85
+ def value(self, value: float) -> None:
86
+ self.set(value)
87
+
88
+ @configure_delegate('value')
89
+ def _delegate_value(self, value=None):
90
+ """Get or set the value via configure."""
91
+ if value is None:
92
+ return self.get()
93
+ self.set(value)
94
+
95
+