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,124 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import ttk
4
+ from typing import Any, Callable, Literal, Optional, TYPE_CHECKING, TypedDict
5
+
6
+ from typing_extensions import Unpack
7
+
8
+ from bootstack.core.mixins.ttk_state import TtkStateMixin
9
+ from bootstack.core.mixins.widget import WidgetCapabilitiesMixin
10
+ from bootstack.widgets.internal.wrapper_base import TTKWrapperBase
11
+ from bootstack.widgets.mixins import IconMixin, LocalizationMixin, SignalMixin, TextSignalMixin
12
+ from bootstack.widgets.mixins.configure_mixin import configure_delegate
13
+ from bootstack.widgets.types import Master
14
+
15
+ if TYPE_CHECKING:
16
+ from bootstack.core.signals import Signal
17
+
18
+
19
+ class CheckButtonKwargs(TypedDict, total=False):
20
+ # Standard ttk.Checkbutton options
21
+ text: Any
22
+ command: Optional[Callable[[], Any]]
23
+ image: Any
24
+ icon: Any
25
+ icon_only: bool
26
+ compound: Literal['text', 'image', 'top', 'bottom', 'left', 'right', 'center', 'none'] | str
27
+ variable: Any
28
+ signal: Signal[Any]
29
+ value: Any
30
+ onvalue: Any
31
+ offvalue: Any
32
+ padding: Any
33
+ anchor: str
34
+ width: int
35
+ underline: int
36
+ state: Literal['normal', 'active', 'disabled', 'readonly'] | str
37
+ takefocus: Any
38
+ style: str
39
+ class_: str
40
+ cursor: str
41
+ name: str
42
+ textvariable: Any
43
+ textsignal: Signal[str]
44
+
45
+ # bootstack-specific extensions
46
+ bootstyle: str # DEPRECATED: Use accent and variant instead
47
+ accent: str
48
+ variant: str
49
+ surface: str
50
+ style_options: dict[str, Any]
51
+ localize: bool | Literal['auto']
52
+
53
+
54
+ class CheckButton(LocalizationMixin, SignalMixin, TextSignalMixin, IconMixin, TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Checkbutton):
55
+ """bootstack wrapper for `ttk.Checkbutton` with bootstyle and icon support."""
56
+
57
+ _ttk_base = ttk.Checkbutton
58
+
59
+ def __init__(self, master: Master = None, **kwargs: Unpack[CheckButtonKwargs]) -> None:
60
+ """Create a themed bootstack Checkbutton.
61
+
62
+ Args:
63
+ master: Parent widget. If None, uses the default root window.
64
+
65
+ Other Parameters:
66
+ text (str): Text to display.
67
+ textvariable (Variable): Tk variable linked to the text.
68
+ textsignal (Signal[str]): Reactive Signal linked to the text (auto-synced with textvariable).
69
+ command (Callable): Callable invoked when the value toggles.
70
+ image (PhotoImage): Image to display.
71
+ icon (str | dict): Theme-aware icon spec handled by the style system.
72
+ icon_only (bool): If True, removes the additional padding reserved for text.
73
+ compound (str): Placement of the image relative to text.
74
+ variable (Variable): Linked variable controlling the on/off state.
75
+ localize (bool | Literal['auto']): Determines the widget's localization mode.
76
+ signal (Signal): Reactive Signal controlling the on/off state (auto-synced with variable).
77
+ value (Any): Initial state for the widget's associated variable (defaults to None when unset).
78
+ onvalue (Any): Value set in `variable` when selected.
79
+ offvalue (Any): Value set in `variable` when deselected.
80
+ padding (int | tuple): Extra space around the content.
81
+ anchor (str): Determines how the content is aligned in the container. Combination of 'n', 's', 'e', 'w', or 'center' (default).
82
+ width (int): Width of the control in characters.
83
+ underline (int): Index of character to underline in `text`.
84
+ state (str): Widget state.
85
+ takefocus (bool): Whether the widget participates in focus traversal.
86
+ style (str): Explicit ttk style name (overrides accent/variant).
87
+ accent (str): Accent token for styling, e.g. 'primary', 'success', 'danger'.
88
+ variant (str): Style variant, e.g. 'default', 'round', 'square'.
89
+ bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
90
+ Combined style tokens (e.g., 'primary', 'success').
91
+ surface (str): Optional surface token; otherwise inherited.
92
+ style_options (dict): Optional dict forwarded to the style builder.
93
+ """
94
+ signal_provided = 'signal' in kwargs
95
+ variable_provided = 'variable' in kwargs
96
+ initial_value = kwargs.pop('value', None)
97
+ kwargs.update(style_options=self._capture_style_options(['icon_only', 'icon', 'anchor'], kwargs))
98
+ super().__init__(master, **kwargs)
99
+ if initial_value is not None and not signal_provided and not variable_provided:
100
+ self.variable.set(initial_value)
101
+
102
+ def get(self) -> Any:
103
+ """Return the current value of the checkbutton."""
104
+ return self.variable.get()
105
+
106
+ def set(self, value: Any) -> None:
107
+ """Set the value of the checkbutton."""
108
+ self.variable.set(value)
109
+
110
+ @property
111
+ def value(self) -> Any:
112
+ """Get or set the checkbutton's value."""
113
+ return self.get()
114
+
115
+ @value.setter
116
+ def value(self, value: Any) -> None:
117
+ self.set(value)
118
+
119
+ @configure_delegate('value')
120
+ def _delegate_value(self, value=None):
121
+ """Get or set the value via configure."""
122
+ if value is None:
123
+ return self.get()
124
+ self.set(value)
@@ -0,0 +1,53 @@
1
+ from typing import Literal
2
+
3
+ from bootstack.widgets.primitives.checkbutton import CheckButton
4
+ from bootstack.widgets.types import Master
5
+
6
+
7
+ class CheckToggle(CheckButton):
8
+ """bootstack wrapper for `ttk.Checkbutton` that renders with a ToolButton style"""
9
+
10
+ def __init__(self, master: Master = None, **kwargs):
11
+ """Create a themed bootstack CheckToggle.
12
+
13
+ Args:
14
+ master: Parent widget. If None, uses the default root window.
15
+
16
+ Other Parameters:
17
+ text (str): Text to display on the toggle.
18
+ textvariable (Variable): Tk variable linked to the text.
19
+ textsignal (Signal[str]): Reactive Signal linked to the text (auto-synced with textvariable).
20
+ command (Callable): Callable invoked when the toggle changes state.
21
+ image (PhotoImage): Image to display.
22
+ icon (str | dict): Theme-aware icon spec handled by the style system.
23
+ icon_only (bool): If True, removes the additional padding reserved for text.
24
+ compound (str): Placement of the image relative to text.
25
+ variable (Variable): Linked variable controlling the on/off state.
26
+ signal (Signal): Reactive Signal controlling the on/off state (auto-synced with variable).
27
+ value (Any): Initial state for the widget's associated variable (defaults to None when unset).
28
+ onvalue (Any): Value set in `variable` when selected.
29
+ offvalue (Any): Value set in `variable` when deselected.
30
+ padding (int | tuple): Extra space around the content.
31
+ anchor (str): Determines how the content is aligned in the container. Combination of 'n', 's', 'e', 'w', or 'center' (default).
32
+ density (str): The vertical and horizontal compactness of widget content, e.g. 'default', 'compact'.
33
+ width (int): Width of the control in characters.
34
+ underline (int): Index of character to underline in `text`.
35
+ state (str): Widget state ('normal', 'active', 'disabled', 'readonly').
36
+ takefocus (bool): Whether the widget participates in focus traversal.
37
+ accent (str): Accent token for styling, e.g. 'primary', 'success', 'danger'.
38
+ variant (str): Style variant (coerced to 'toolbutton').
39
+ surface (str): Optional surface token; otherwise inherited.
40
+ style_options (dict): Optional dict forwarded to the style builder.
41
+ localize (bool | Literal['auto']): Determines the widget's localization mode.
42
+ """
43
+ self._capture_density_option(kwargs)
44
+ kwargs.setdefault('class_', 'Toolbutton')
45
+ super().__init__(master, **kwargs)
46
+
47
+ @staticmethod
48
+ def _capture_density_option(kwargs: dict) -> None:
49
+ """Capture density from kwargs into style_options."""
50
+ density: Literal['default', 'compact'] | None = kwargs.pop('density', None)
51
+ if density is not None:
52
+ style_options = kwargs.setdefault('style_options', {})
53
+ style_options['density'] = density
@@ -0,0 +1,165 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import ttk
4
+ from typing import Any, Literal, TypedDict, TYPE_CHECKING
5
+
6
+ from typing_extensions import Unpack
7
+
8
+ from bootstack.core.mixins.ttk_state import TtkStateMixin
9
+ from bootstack.core.mixins.widget import WidgetCapabilitiesMixin
10
+ from bootstack.widgets.internal.wrapper_base import TTKWrapperBase
11
+ from bootstack.widgets.types import Master
12
+ from ..mixins import TextSignalMixin, configure_delegate
13
+
14
+ if TYPE_CHECKING:
15
+ from bootstack.core.signals import Signal
16
+
17
+
18
+ class ComboboxKwargs(TypedDict, total=False):
19
+ # Standard ttk.Combobox options
20
+ values: Any
21
+ textvariable: Any
22
+ textsignal: Signal[Any]
23
+ state: Literal['normal', 'readonly', 'disabled'] | str
24
+ width: int
25
+ height: int
26
+ postcommand: Any
27
+ justify: Any
28
+ exportselection: bool
29
+ xscrollcommand: Any
30
+ font: Any
31
+ foreground: str
32
+ background: str
33
+ style: str
34
+ class_: str
35
+ cursor: str
36
+ name: str
37
+
38
+ # bootstack-specific extensions
39
+ bootstyle: str # DEPRECATED: Use accent and variant instead
40
+ accent: str
41
+ density: Literal['default', 'compact']
42
+ surface: str
43
+ style_options: dict[str, Any]
44
+
45
+
46
+ class Combobox(TextSignalMixin, TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Combobox):
47
+ """bootstack wrapper for `ttk.Combobox` with bootstyle support."""
48
+
49
+ _ttk_base = ttk.Combobox
50
+
51
+ def __init__(self, master: Master = None, **kwargs: Unpack[ComboboxKwargs]) -> None:
52
+ """Create a themed bootstack Combobox.
53
+
54
+ Args:
55
+ master: Parent widget. If None, uses the default root window.
56
+
57
+ Other Parameters:
58
+ values (list): Sequence of values to display.
59
+ textvariable (Variable): Tk variable linked to the selected value.
60
+ textsignal (Signal): Reactive Signal linked to the text (auto-synced with textvariable).
61
+ state (str): Widget state; 'readonly' restricts to list items.
62
+ width (int): Width in characters.
63
+ height (int): Maximum rows shown in the drop-down list.
64
+ postcommand (Callable): Callback executed before showing the drop-down.
65
+ justify (str): Text justification within the entry field.
66
+ exportselection (bool): Whether selection is exported to X clipboard.
67
+ xscrollcommand (Callable): Scroll callback for horizontal scrolling.
68
+ font (str | Font): Font for the entry field.
69
+ foreground (str): Text color.
70
+ background (str): Background color for the entry field.
71
+ style (str): Explicit ttk style name (overrides accent/variant).
72
+ accent (str): Accent token for styling, e.g. 'primary', 'danger', 'success'.
73
+ density (str): The vertical and horizontal compactness, e.g. 'default', 'compact'.
74
+ bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
75
+ Combined style tokens (e.g., 'primary').
76
+ surface (str): Optional surface token; otherwise inherited.
77
+ style_options (dict): Optional dict forwarded to the style builder.
78
+ """
79
+ # Store density for popdown positioning
80
+ if kwargs.get('density') == 'compact':
81
+ kwargs['font'] = 'caption'
82
+ kwargs.update(style_options=self._capture_style_options(['density'], kwargs))
83
+ super().__init__(master, **kwargs)
84
+
85
+ # Store original postcommand if provided
86
+ self._original_postcommand = kwargs.get('postcommand')
87
+
88
+ # Set up popdown styling (also bound to theme changes)
89
+ self._setup_postcommand()
90
+ self._subscribe_theme_changes()
91
+
92
+ @configure_delegate('density')
93
+ def _delegate_density(self, value=None):
94
+ if value is None:
95
+ return self.configure_style_options(value)
96
+ else:
97
+ if value == 'compact':
98
+ self.configure(font='caption')
99
+ else:
100
+ self.configure(font='body')
101
+ return self.configure_style_options(density=value)
102
+
103
+ def _setup_postcommand(self) -> None:
104
+ """Re-style the popdown each time it opens.
105
+
106
+ The popdown is created lazily on first open and reused. Re-styling on
107
+ every open ensures it picks up the current theme's colors, since the
108
+ embedded Tk listbox/scrollbar aren't rebuilt by the ttk style engine.
109
+ """
110
+
111
+ def on_popdown():
112
+ self._apply_popdown_style(create_if_missing=True)
113
+
114
+ if self._original_postcommand:
115
+ if callable(self._original_postcommand):
116
+ self._original_postcommand()
117
+ else:
118
+ self.tk.eval(str(self._original_postcommand))
119
+
120
+ self.configure(postcommand=on_popdown)
121
+
122
+ def _apply_popdown_style(self, create_if_missing: bool = False) -> None:
123
+ """Apply theme colors and density font to the embedded popdown.
124
+
125
+ Args:
126
+ create_if_missing: If True, force-create the popdown so we can
127
+ style it before it's mapped (used from the postcommand). If
128
+ False, no-op when the popdown doesn't exist yet (used from
129
+ the theme-change subscriber).
130
+ """
131
+ popdown_path = f"{self}.popdown"
132
+ try:
133
+ popdown_exists = bool(int(self.tk.eval(f"winfo exists {popdown_path}")))
134
+ except Exception:
135
+ return
136
+
137
+ if not popdown_exists:
138
+ if not create_if_missing:
139
+ return
140
+ try:
141
+ self.tk.eval(f"ttk::combobox::PopdownWindow {self}")
142
+ except Exception:
143
+ return
144
+
145
+ try:
146
+ from bootstack.style.bootstyle_builder_mixed import BootstyleBuilderMixed
147
+ BootstyleBuilderMixed().update_combobox_popdown_style(self)
148
+ except Exception:
149
+ pass
150
+
151
+ try:
152
+ density = self.configure_style_options('density') or 'default'
153
+ from bootstack.style.typography import get_font
154
+ font_token = 'caption' if density == 'compact' else 'body'
155
+ self.tk.call(f"{popdown_path}.f.l", "configure", "-font", str(get_font(font_token)))
156
+ except Exception:
157
+ pass
158
+
159
+ def _subscribe_theme_changes(self) -> None:
160
+ """Re-style any already-created popdown when the theme changes."""
161
+ from bootstack.core.publisher import Channel, Publisher
162
+ name = str(self)
163
+ Publisher.subscribe(name=name, func=self._apply_popdown_style, channel=Channel.STD)
164
+ self.bind('<Destroy>', lambda _e, n=name: Publisher.unsubscribe(n), '+')
165
+
@@ -0,0 +1,98 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import ttk
4
+ from typing import Any, Literal, Optional, 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.types import Master
11
+ from ..mixins import TextSignalMixin, configure_delegate
12
+
13
+ if TYPE_CHECKING:
14
+ from bootstack.core.signals import Signal
15
+
16
+
17
+ class EntryKwargs(TypedDict, total=False):
18
+ # Standard ttk.Entry options
19
+ textvariable: Any
20
+ textsignal: Signal[str]
21
+ show: Any
22
+ width: int
23
+ exportselection: bool
24
+ justify: Any
25
+ validate: Any
26
+ validatecommand: Any
27
+ invalidcommand: Any
28
+ xscrollcommand: Any
29
+ font: Any
30
+ foreground: str
31
+ background: str
32
+ state: Literal['normal', 'disabled', 'readonly'] | str
33
+ takefocus: Any
34
+ style: str
35
+ class_: str
36
+ cursor: str
37
+ name: str
38
+
39
+ # bootstack-specific extensions
40
+ bootstyle: str # DEPRECATED: Use accent and variant instead
41
+ accent: str
42
+ density: Literal['default', 'compact']
43
+ variant: str
44
+ surface: str
45
+ style_options: dict[str, Any]
46
+
47
+
48
+ class Entry(TextSignalMixin, TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Entry):
49
+ """bootstack wrapper for `ttk.Entry` with bootstyle support."""
50
+
51
+ _ttk_base = ttk.Entry
52
+
53
+ def __init__(self, master: Master = None, **kwargs: Unpack[EntryKwargs]) -> None:
54
+ """Create a themed bootstack Entry.
55
+
56
+ Args:
57
+ master: Parent widget. If None, uses the default root window.
58
+
59
+ Other Parameters:
60
+ textvariable (Variable): Tk variable linked to the entry text.
61
+ textsignal (Signal[str]): Reactive Signal linked to the entry text (auto-synced with textvariable).
62
+ show (str): Substitute character for masked input.
63
+ width (int): Width in characters.
64
+ exportselection (bool): Whether selection is exported to X clipboard.
65
+ justify (str): Text alignment inside the entry.
66
+ validate (str): Validation mode.
67
+ validatecommand (Callable): Validation callback.
68
+ invalidcommand (Callable): Callback executed on validation failure.
69
+ xscrollcommand (Callable): Horizontal scroll callback.
70
+ font (str | Font): Font for the entry text.
71
+ foreground (str): Text color.
72
+ background (str): Background color.
73
+ state (str): Widget state.
74
+ takefocus (bool): Whether the widget participates in focus traversal.
75
+ style (str): Explicit ttk style name (overrides accent/variant).
76
+ accent (str): Accent token for styling, e.g. 'primary', 'danger', 'success'.
77
+ variant (str): Style variant, e.g. 'default'.
78
+ density (str): The vertical and horizontal compactness, e.g. 'default', 'compact'.
79
+ bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
80
+ Combined style tokens (e.g., 'primary').
81
+ surface (str): Optional surface token; otherwise inherited.
82
+ style_options (dict): Optional dict forwarded to the style builder.
83
+ """
84
+ if kwargs.get('density') == 'compact':
85
+ kwargs['font'] = 'caption'
86
+ kwargs.update(style_options=self._capture_style_options(['density'], kwargs))
87
+ super().__init__(master, **kwargs)
88
+
89
+ @configure_delegate('density')
90
+ def _delegate_density(self, value=None):
91
+ if value is None:
92
+ return self.configure_style_options(value)
93
+ else:
94
+ if value == 'compact':
95
+ self.configure(font='caption')
96
+ else:
97
+ self.configure(font='body')
98
+ return self.configure_style_options(density=value)
@@ -0,0 +1,206 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import ttk
4
+ from typing import Any, TypedDict
5
+
6
+ from typing_extensions import Unpack
7
+
8
+ from bootstack.core.mixins.ttk_state import TtkStateMixin
9
+ from bootstack.core.mixins.widget import WidgetCapabilitiesMixin
10
+ from bootstack.widgets.internal.wrapper_base import TTKWrapperBase
11
+ from bootstack.widgets.types import Master
12
+ from bootstack.style.style import get_style
13
+ from bootstack.style.bootstyle_builder_tk import BootstyleBuilderBuilderTk
14
+ from ..mixins import configure_delegate
15
+
16
+
17
+ class FrameKwargs(TypedDict, total=False):
18
+ # Standard ttk.Frame options
19
+ padding: Any
20
+ width: int
21
+ height: int
22
+ style: str
23
+ cursor: str
24
+ name: str
25
+ takefocus: bool
26
+ class_: str
27
+
28
+ # bootstack-specific extensions
29
+ accent: str
30
+ variant: str
31
+ surface: str
32
+ input_background: str
33
+ show_border: bool
34
+ style_options: dict[str, Any]
35
+ bootstyle: str # DEPRECATED: Use accent and variant instead
36
+
37
+
38
+ class Frame(TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Frame):
39
+ """bootstack wrapper for `ttk.Frame` with bootstyle support."""
40
+
41
+ _ttk_base = ttk.Frame
42
+
43
+ def __init__(self, master: Master = None, **kwargs: Unpack[FrameKwargs]) -> None:
44
+ """Create a themed bootstack Frame.
45
+
46
+ Args:
47
+ master: Parent widget. If None, uses the default root window.
48
+
49
+ Other Parameters:
50
+ padding (int | tuple): Extra padding inside the frame.
51
+ relief (str): Border style.
52
+ borderwidth (int): Border width.
53
+ width (int): Requested width in pixels.
54
+ height (int): Requested height in pixels.
55
+ takefocus (bool): Widget accepts focus during keyboard traversal.
56
+ style (str): Explicit ttk style name (overrides accent/variant).
57
+ accent (str): Accent token for styling, e.g. 'primary', 'secondary', 'success'.
58
+ variant (str): Style variant (if applicable).
59
+ bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
60
+ Combined style tokens (e.g., 'secondary').
61
+ surface (str): Optional surface token; otherwise inherited.
62
+ input_background (str): Surface token used as the fill color for all input
63
+ widgets (Entry, Combobox, Spinbox, Field) inside this container. Cascades
64
+ to descendants the same way `surface` does. Input foreground, border,
65
+ and focus-ring colors are all derived from this fill so contrast is always
66
+ correct. Defaults to `'content'` (the app background), which keeps
67
+ inputs visually distinct regardless of the container surface. Override
68
+ with any surface token (e.g. `'card'`) to match the container.
69
+ show_border (bool): Draw a border around the frame.
70
+ style_options (dict): Optional dict forwarded to the style builder.
71
+ """
72
+ kwargs.update(style_options=self._capture_style_options(['show_border'], kwargs))
73
+ super().__init__(master, **kwargs)
74
+
75
+ def configure_style_options(self, value=None, **kwargs):
76
+ """Set style options and refresh descendant surfaces if needed."""
77
+ old_surface = getattr(self, "_surface", "background")
78
+ old_input_bg = getattr(self, "_input_background", None)
79
+ result = super().configure_style_options(value, **kwargs)
80
+ if value is None:
81
+ if "surface" in kwargs:
82
+ new_surface = getattr(self, "_surface", "background")
83
+ if old_surface != new_surface:
84
+ self.rebuild_style()
85
+ self._refresh_descendant_surfaces(old_surface, new_surface)
86
+ if "input_background" in kwargs:
87
+ new_input_bg = getattr(self, "_input_background", None)
88
+ if old_input_bg != new_input_bg:
89
+ self._refresh_descendant_input_backgrounds(old_input_bg, new_input_bg)
90
+ return result
91
+
92
+ @configure_delegate("bootstyle")
93
+ def _delegate_bootstyle(self, value: Any = None):
94
+ old_surface = getattr(self, "_surface", "background")
95
+ result = super()._delegate_bootstyle(value)
96
+ new_surface = getattr(self, "_surface", "background")
97
+ if value is not None and old_surface != new_surface:
98
+ self._refresh_descendant_surfaces(old_surface, new_surface)
99
+ return result
100
+
101
+ def _refresh_descendant_surfaces(self, old_surface: str, new_surface: str) -> None:
102
+ if old_surface == new_surface:
103
+ return
104
+
105
+ style = get_style()
106
+ builder_tk = BootstyleBuilderBuilderTk(
107
+ theme_provider=style.theme_provider if style else None,
108
+ style_instance=style,
109
+ )
110
+
111
+ for child in self._iter_descendants():
112
+ try:
113
+ child_surface = getattr(child, "_surface", None)
114
+ except Exception:
115
+ child_surface = None
116
+
117
+ explicit_surface = None
118
+ try:
119
+ explicit_surface = getattr(child, "_style_options", {}).get("surface")
120
+ except Exception:
121
+ explicit_surface = None
122
+
123
+ if explicit_surface and explicit_surface != old_surface:
124
+ continue
125
+
126
+ if child_surface != old_surface:
127
+ continue
128
+
129
+ try:
130
+ setattr(child, "_surface", new_surface)
131
+ except Exception:
132
+ continue
133
+
134
+ if hasattr(child, "rebuild_style"):
135
+ try:
136
+ child.rebuild_style()
137
+ except Exception:
138
+ pass
139
+ else:
140
+ try:
141
+ builder_tk.call_builder(child, surface=new_surface)
142
+ except Exception:
143
+ pass
144
+
145
+ def _refresh_descendant_input_backgrounds(self, old_bg: str | None, new_bg: str | None) -> None:
146
+ if old_bg == new_bg:
147
+ return
148
+
149
+ style = get_style()
150
+ builder_tk = BootstyleBuilderBuilderTk(
151
+ theme_provider=style.theme_provider if style else None,
152
+ style_instance=style,
153
+ )
154
+
155
+ for child in self._iter_descendants():
156
+ try:
157
+ child_input_bg = getattr(child, "_input_background", None)
158
+ except Exception:
159
+ child_input_bg = None
160
+
161
+ explicit_input_bg = None
162
+ try:
163
+ explicit_input_bg = getattr(child, "_style_options", {}).get("input_background")
164
+ except Exception:
165
+ explicit_input_bg = None
166
+
167
+ if explicit_input_bg and explicit_input_bg != old_bg:
168
+ continue
169
+
170
+ if child_input_bg != old_bg:
171
+ continue
172
+
173
+ try:
174
+ setattr(child, "_input_background", new_bg)
175
+ except Exception:
176
+ continue
177
+
178
+ if hasattr(child, "rebuild_style"):
179
+ try:
180
+ child.rebuild_style()
181
+ except Exception:
182
+ pass
183
+ else:
184
+ try:
185
+ builder_tk.call_builder(child, input_background=new_bg)
186
+ except Exception:
187
+ pass
188
+
189
+ def _iter_descendants(self):
190
+ stack = list(self.winfo_children())
191
+ while stack:
192
+ widget = stack.pop()
193
+ yield widget
194
+ try:
195
+ stack.extend(widget.winfo_children())
196
+ except Exception:
197
+ pass
198
+
199
+ @configure_delegate('show_border')
200
+ def _delegate_show_border(self, value=None):
201
+ if value is not None:
202
+ return self.configure_style_options('show_border')
203
+ else:
204
+ self.configure_style_options(show_border=True)
205
+ return self.rebuild_style()
206
+